Remove the Timer parameters from timer callbacks
[WebKit-https.git] / Source / WebCore / svg / SVGElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org>
4  * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
5  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6  * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
7  * Copyright (C) 2013 Samsung Electronics. All rights reserved.
8  * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "SVGElement.h"
28
29 #include "Attr.h"
30 #include "CSSCursorImageValue.h"
31 #include "CSSParser.h"
32 #include "DOMImplementation.h"
33 #include "Document.h"
34 #include "ElementIterator.h"
35 #include "Event.h"
36 #include "EventNames.h"
37 #include "HTMLElement.h"
38 #include "HTMLNames.h"
39 #include "HTMLParserIdioms.h"
40 #include "RenderObject.h"
41 #include "RenderSVGResource.h"
42 #include "RenderSVGResourceClipper.h"
43 #include "RenderSVGResourceFilter.h"
44 #include "RenderSVGResourceMasker.h"
45 #include "SVGCursorElement.h"
46 #include "SVGDocumentExtensions.h"
47 #include "SVGElementInstance.h"
48 #include "SVGElementRareData.h"
49 #include "SVGGraphicsElement.h"
50 #include "SVGImageElement.h"
51 #include "SVGNames.h"
52 #include "SVGRenderStyle.h"
53 #include "SVGRenderSupport.h"
54 #include "SVGSVGElement.h"
55 #include "SVGTitleElement.h"
56 #include "SVGUseElement.h"
57 #include "ShadowRoot.h"
58 #include "XLinkNames.h"
59 #include "XMLNames.h"
60 #include <wtf/Assertions.h>
61 #include <wtf/HashMap.h>
62 #include <wtf/NeverDestroyed.h>
63 #include <wtf/StdLibExtras.h>
64 #include <wtf/text/WTFString.h>
65
66
67 namespace WebCore {
68
69 // Animated property definitions
70 DEFINE_ANIMATED_STRING(SVGElement, HTMLNames::classAttr, ClassName, className)
71
72 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGElement)
73     REGISTER_LOCAL_ANIMATED_PROPERTY(className)
74 END_REGISTER_ANIMATED_PROPERTIES
75
76 using namespace HTMLNames;
77 using namespace SVGNames;
78
79 static NEVER_INLINE void populateAttributeNameToCSSPropertyIDMap(HashMap<AtomicStringImpl*, CSSPropertyID>& map)
80 {
81     // This list should include all base CSS and SVG CSS properties which are exposed as SVG XML attributes.
82     static const QualifiedName* const attributeNames[] = {
83         &alignment_baselineAttr,
84         &baseline_shiftAttr,
85         &buffered_renderingAttr,
86         &clipAttr,
87         &clip_pathAttr,
88         &clip_ruleAttr,
89         &SVGNames::colorAttr,
90         &color_interpolationAttr,
91         &color_interpolation_filtersAttr,
92         &color_profileAttr,
93         &color_renderingAttr,
94         &cursorAttr,
95         &cxAttr,
96         &cyAttr,
97         &SVGNames::directionAttr,
98         &displayAttr,
99         &dominant_baselineAttr,
100         &enable_backgroundAttr,
101         &fillAttr,
102         &fill_opacityAttr,
103         &fill_ruleAttr,
104         &filterAttr,
105         &flood_colorAttr,
106         &flood_opacityAttr,
107         &font_familyAttr,
108         &font_sizeAttr,
109         &font_stretchAttr,
110         &font_styleAttr,
111         &font_variantAttr,
112         &font_weightAttr,
113         &glyph_orientation_horizontalAttr,
114         &glyph_orientation_verticalAttr,
115         &image_renderingAttr,
116         &SVGNames::heightAttr,
117         &kerningAttr,
118         &letter_spacingAttr,
119         &lighting_colorAttr,
120         &marker_endAttr,
121         &marker_midAttr,
122         &marker_startAttr,
123         &maskAttr,
124         &mask_typeAttr,
125         &opacityAttr,
126         &overflowAttr,
127         &paint_orderAttr,
128         &pointer_eventsAttr,
129         &rAttr,
130         &rxAttr,
131         &ryAttr,
132         &shape_renderingAttr,
133         &stop_colorAttr,
134         &stop_opacityAttr,
135         &strokeAttr,
136         &stroke_dasharrayAttr,
137         &stroke_dashoffsetAttr,
138         &stroke_linecapAttr,
139         &stroke_linejoinAttr,
140         &stroke_miterlimitAttr,
141         &stroke_opacityAttr,
142         &stroke_widthAttr,
143         &text_anchorAttr,
144         &text_decorationAttr,
145         &text_renderingAttr,
146         &unicode_bidiAttr,
147         &vector_effectAttr,
148         &visibilityAttr,
149         &SVGNames::widthAttr,
150         &word_spacingAttr,
151         &writing_modeAttr,
152         &xAttr,
153         &yAttr,
154     };
155
156     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(attributeNames); ++i) {
157         const AtomicString& localName = attributeNames[i]->localName();
158         map.add(localName.impl(), cssPropertyID(localName));
159     }
160
161     // FIXME: When CSS supports "transform-origin" this special case can be removed,
162     // and we can add transform_originAttr to the table above instead.
163     map.add(transform_originAttr.localName().impl(), CSSPropertyWebkitTransformOrigin);
164 }
165
166 static NEVER_INLINE void populateAttributeNameToAnimatedPropertyTypeMap(HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>& map)
167 {
168     struct TableEntry {
169         const QualifiedName& attributeName;
170         AnimatedPropertyType type;
171     };
172
173     static const TableEntry table[] = {
174         { alignment_baselineAttr, AnimatedString },
175         { baseline_shiftAttr, AnimatedString },
176         { buffered_renderingAttr, AnimatedString },
177         { clipAttr, AnimatedRect },
178         { clip_pathAttr, AnimatedString },
179         { clip_ruleAttr, AnimatedString },
180         { SVGNames::colorAttr, AnimatedColor },
181         { color_interpolationAttr, AnimatedString },
182         { color_interpolation_filtersAttr, AnimatedString },
183         { color_profileAttr, AnimatedString },
184         { color_renderingAttr, AnimatedString },
185         { cursorAttr, AnimatedString },
186         { displayAttr, AnimatedString },
187         { dominant_baselineAttr, AnimatedString },
188         { fillAttr, AnimatedColor },
189         { fill_opacityAttr, AnimatedNumber },
190         { fill_ruleAttr, AnimatedString },
191         { filterAttr, AnimatedString },
192         { flood_colorAttr, AnimatedColor },
193         { flood_opacityAttr, AnimatedNumber },
194         { font_familyAttr, AnimatedString },
195         { font_sizeAttr, AnimatedLength },
196         { font_stretchAttr, AnimatedString },
197         { font_styleAttr, AnimatedString },
198         { font_variantAttr, AnimatedString },
199         { font_weightAttr, AnimatedString },
200         { image_renderingAttr, AnimatedString },
201         { kerningAttr, AnimatedLength },
202         { letter_spacingAttr, AnimatedLength },
203         { lighting_colorAttr, AnimatedColor },
204         { marker_endAttr, AnimatedString },
205         { marker_midAttr, AnimatedString },
206         { marker_startAttr, AnimatedString },
207         { maskAttr, AnimatedString },
208         { mask_typeAttr, AnimatedString },
209         { opacityAttr, AnimatedNumber },
210         { overflowAttr, AnimatedString },
211         { paint_orderAttr, AnimatedString },
212         { pointer_eventsAttr, AnimatedString },
213         { shape_renderingAttr, AnimatedString },
214         { stop_colorAttr, AnimatedColor },
215         { stop_opacityAttr, AnimatedNumber },
216         { strokeAttr, AnimatedColor },
217         { stroke_dasharrayAttr, AnimatedLengthList },
218         { stroke_dashoffsetAttr, AnimatedLength },
219         { stroke_linecapAttr, AnimatedString },
220         { stroke_linejoinAttr, AnimatedString },
221         { stroke_miterlimitAttr, AnimatedNumber },
222         { stroke_opacityAttr, AnimatedNumber },
223         { stroke_widthAttr, AnimatedLength },
224         { text_anchorAttr, AnimatedString },
225         { text_decorationAttr, AnimatedString },
226         { text_renderingAttr, AnimatedString },
227         { vector_effectAttr, AnimatedString },
228         { visibilityAttr, AnimatedString },
229         { word_spacingAttr, AnimatedLength },
230     };
231
232     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(table); ++i)
233         map.add(table[i].attributeName.impl(), table[i].type);
234 }
235
236 static inline HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>& attributeNameToAnimatedPropertyTypeMap()
237 {
238     static NeverDestroyed<HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>> map;
239     if (map.get().isEmpty())
240         populateAttributeNameToAnimatedPropertyTypeMap(map);
241     return map;
242 }
243
244 static NEVER_INLINE void populateCSSPropertyWithSVGDOMNameToAnimatedPropertyTypeMap(HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>& map)
245 {
246     struct TableEntry {
247         const QualifiedName& attributeName;
248         AnimatedPropertyType type;
249     };
250
251     static const TableEntry table[] = {
252         { cxAttr, AnimatedLength },
253         { cyAttr, AnimatedLength },
254         { rAttr, AnimatedLength },
255         { rxAttr, AnimatedLength },
256         { ryAttr, AnimatedLength },
257         { SVGNames::heightAttr, AnimatedLength },
258         { SVGNames::widthAttr, AnimatedLength },
259         { xAttr, AnimatedLength },
260         { yAttr, AnimatedLength },
261     };
262
263     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(table); ++i)
264         map.add(table[i].attributeName.impl(), table[i].type);
265 }
266
267 static inline HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>& cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap()
268 {
269     static NeverDestroyed<HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyType>> map;
270     if (map.get().isEmpty())
271         populateCSSPropertyWithSVGDOMNameToAnimatedPropertyTypeMap(map);
272     return map;
273 }
274
275 SVGElement::SVGElement(const QualifiedName& tagName, Document& document)
276     : StyledElement(tagName, document, CreateSVGElement)
277 {
278     registerAnimatedPropertiesForSVGElement();
279 }
280
281 SVGElement::~SVGElement()
282 {
283     if (m_svgRareData) {
284         m_svgRareData->destroyAnimatedSMILStyleProperties();
285         if (SVGCursorElement* cursorElement = m_svgRareData->cursorElement())
286             cursorElement->removeClient(this);
287         if (CSSCursorImageValue* cursorImageValue = m_svgRareData->cursorImageValue())
288             cursorImageValue->removeReferencedElement(this);
289
290         m_svgRareData = nullptr;
291     }
292     document().accessSVGExtensions().rebuildAllElementReferencesForTarget(*this);
293     document().accessSVGExtensions().removeAllElementReferencesForTarget(this);
294 }
295
296 short SVGElement::tabIndex() const
297 {
298     if (supportsFocus())
299         return Element::tabIndex();
300     return -1;
301 }
302
303 bool SVGElement::willRecalcStyle(Style::Change change)
304 {
305     if (!m_svgRareData || styleChangeType() == SyntheticStyleChange)
306         return true;
307     // If the style changes because of a regular property change (not induced by SMIL animations themselves)
308     // reset the "computed style without SMIL style properties", so the base value change gets reflected.
309     if (change > Style::NoChange || needsStyleRecalc())
310         m_svgRareData->setNeedsOverrideComputedStyleUpdate();
311     return true;
312 }
313
314 SVGElementRareData& SVGElement::ensureSVGRareData()
315 {
316     if (!m_svgRareData)
317         m_svgRareData = std::make_unique<SVGElementRareData>();
318     return *m_svgRareData;
319 }
320
321 bool SVGElement::isOutermostSVGSVGElement() const
322 {
323     if (!is<SVGSVGElement>(*this))
324         return false;
325
326     // If we're living in a shadow tree, we're a <svg> element that got created as replacement
327     // for a <symbol> element or a cloned <svg> element in the referenced tree. In that case
328     // we're always an inner <svg> element.
329     if (isInShadowTree() && parentOrShadowHostElement() && parentOrShadowHostElement()->isSVGElement())
330         return false;
331
332     // Element may not be in the document, pretend we're outermost for viewport(), getCTM(), etc.
333     if (!parentNode())
334         return true;
335
336     // We act like an outermost SVG element, if we're a direct child of a <foreignObject> element.
337     if (parentNode()->hasTagName(SVGNames::foreignObjectTag))
338         return true;
339
340     // This is true whenever this is the outermost SVG, even if there are HTML elements outside it
341     return !parentNode()->isSVGElement();
342 }
343
344 void SVGElement::reportAttributeParsingError(SVGParsingError error, const QualifiedName& name, const AtomicString& value)
345 {
346     if (error == NoError)
347         return;
348
349     String errorString = "<" + tagName() + "> attribute " + name.toString() + "=\"" + value + "\"";
350     SVGDocumentExtensions& extensions = document().accessSVGExtensions();
351
352     if (error == NegativeValueForbiddenError) {
353         extensions.reportError("Invalid negative value for " + errorString);
354         return;
355     }
356
357     if (error == ParsingAttributeFailedError) {
358         extensions.reportError("Invalid value for " + errorString);
359         return;
360     }
361
362     ASSERT_NOT_REACHED();
363 }
364
365 bool SVGElement::isSupported(StringImpl* feature, StringImpl* version) const
366 {
367     return DOMImplementation::hasFeature(feature, version);
368 }
369
370 String SVGElement::xmlbase() const
371 {
372     return fastGetAttribute(XMLNames::baseAttr);
373 }
374
375 void SVGElement::setXmlbase(const String& value, ExceptionCode&)
376 {
377     setAttribute(XMLNames::baseAttr, value);
378 }
379
380 void SVGElement::removedFrom(ContainerNode& rootParent)
381 {
382     bool wasInDocument = rootParent.inDocument();
383     if (wasInDocument)
384         updateRelativeLengthsInformation(false, this);
385
386     StyledElement::removedFrom(rootParent);
387
388     if (wasInDocument) {
389         document().accessSVGExtensions().clearTargetDependencies(*this);
390         document().accessSVGExtensions().removeAllElementReferencesForTarget(this);
391     }
392     SVGElementInstance::invalidateAllInstancesOfElement(this);
393 }
394
395 SVGSVGElement* SVGElement::ownerSVGElement() const
396 {
397     ContainerNode* node = parentOrShadowHostNode();
398     while (node) {
399         if (is<SVGSVGElement>(*node))
400             return downcast<SVGSVGElement>(node);
401
402         node = node->parentOrShadowHostNode();
403     }
404
405     return nullptr;
406 }
407
408 SVGElement* SVGElement::viewportElement() const
409 {
410     // This function needs shadow tree support - as RenderSVGContainer uses this function
411     // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise.
412     ContainerNode* node = parentOrShadowHostNode();
413     while (node) {
414         if (is<SVGSVGElement>(*node) || is<SVGImageElement>(*node) || node->hasTagName(SVGNames::symbolTag))
415             return downcast<SVGElement>(node);
416
417         node = node->parentOrShadowHostNode();
418     }
419
420     return nullptr;
421 }
422  
423 void SVGElement::mapInstanceToElement(SVGElementInstance* instance)
424 {
425     ASSERT(instance);
426
427     HashSet<SVGElementInstance*>& instances = ensureSVGRareData().elementInstances();
428     ASSERT(!instances.contains(instance));
429
430     instances.add(instance);
431 }
432  
433 void SVGElement::removeInstanceMapping(SVGElementInstance* instance)
434 {
435     ASSERT(instance);
436     ASSERT(m_svgRareData);
437
438     HashSet<SVGElementInstance*>& instances = m_svgRareData->elementInstances();
439     ASSERT(instances.contains(instance));
440
441     instances.remove(instance);
442 }
443
444 const HashSet<SVGElementInstance*>& SVGElement::instancesForElement() const
445 {
446     if (!m_svgRareData) {
447         static NeverDestroyed<HashSet<SVGElementInstance*>> emptyInstances;
448         return emptyInstances;
449     }
450     return m_svgRareData->elementInstances();
451 }
452
453 bool SVGElement::getBoundingBox(FloatRect& rect, SVGLocatable::StyleUpdateStrategy styleUpdateStrategy)
454 {
455     if (is<SVGGraphicsElement>(*this)) {
456         rect = downcast<SVGGraphicsElement>(*this).getBBox(styleUpdateStrategy);
457         return true;
458     }
459     return false;
460 }
461
462 void SVGElement::setCursorElement(SVGCursorElement* cursorElement)
463 {
464     SVGElementRareData& rareData = ensureSVGRareData();
465     if (SVGCursorElement* oldCursorElement = rareData.cursorElement()) {
466         if (cursorElement == oldCursorElement)
467             return;
468         oldCursorElement->removeReferencedElement(this);
469     }
470     rareData.setCursorElement(cursorElement);
471 }
472
473 void SVGElement::cursorElementRemoved() 
474 {
475     ASSERT(m_svgRareData);
476     m_svgRareData->setCursorElement(0);
477 }
478
479 void SVGElement::setCursorImageValue(CSSCursorImageValue* cursorImageValue)
480 {
481     SVGElementRareData& rareData = ensureSVGRareData();
482     if (CSSCursorImageValue* oldCursorImageValue = rareData.cursorImageValue()) {
483         if (cursorImageValue == oldCursorImageValue)
484             return;
485         oldCursorImageValue->removeReferencedElement(this);
486     }
487     rareData.setCursorImageValue(cursorImageValue);
488 }
489
490 void SVGElement::cursorImageValueRemoved()
491 {
492     ASSERT(m_svgRareData);
493     m_svgRareData->setCursorImageValue(0);
494 }
495
496 SVGElement* SVGElement::correspondingElement()
497 {
498     ASSERT(!m_svgRareData || !m_svgRareData->correspondingElement() || containingShadowRoot());
499     return m_svgRareData ? m_svgRareData->correspondingElement() : 0;
500 }
501
502 void SVGElement::setCorrespondingElement(SVGElement* correspondingElement)
503 {
504     ensureSVGRareData().setCorrespondingElement(correspondingElement);
505 }
506
507 void SVGElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
508 {
509     if (name == HTMLNames::classAttr)
510         setClassNameBaseValue(value);
511     else if (name == tabindexAttr) {
512         int tabindex = 0;
513         if (value.isEmpty())
514             clearTabIndexExplicitlyIfNeeded();
515         else if (parseHTMLInteger(value, tabindex)) {
516             // Clamp tabindex to the range of 'short' to match Firefox's behavior.
517             setTabIndexExplicitly(std::max(static_cast<int>(std::numeric_limits<short>::min()), std::min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
518         }
519     } else if (SVGLangSpace::parseAttribute(name, value))
520         return;
521     else {
522         // FIXME: Can we do this even faster by checking the local name "on" prefix before we do anything with the map?
523         // See HTMLElement::parseAttribute().
524         static NeverDestroyed<HashMap<AtomicStringImpl*, AtomicString>> eventNamesGlobal;
525         auto& eventNames = eventNamesGlobal.get();
526         if (eventNames.isEmpty())
527             HTMLElement::populateEventNameForAttributeLocalNameMap(eventNames);
528         const AtomicString& eventName = eventNames.get(name.localName().impl());
529         if (!eventName.isNull())
530             setAttributeEventListener(eventName, name, value);
531         else
532             StyledElement::parseAttribute(name, value);
533     }
534 }
535
536 void SVGElement::animatedPropertyTypeForAttribute(const QualifiedName& attributeName, Vector<AnimatedPropertyType>& propertyTypes)
537 {
538     localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName, propertyTypes);
539     if (!propertyTypes.isEmpty())
540         return;
541
542     auto& map = attributeNameToAnimatedPropertyTypeMap();
543     auto it = map.find(attributeName.impl());
544     if (it != map.end()) {
545         propertyTypes.append(it->value);
546         return;
547     }
548
549     auto& cssPropertyWithSVGDOMMap = cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap();
550     auto svgPropertyIterator = cssPropertyWithSVGDOMMap.find(attributeName.impl());
551     if (svgPropertyIterator != cssPropertyWithSVGDOMMap.end())
552         propertyTypes.append(svgPropertyIterator->value);
553 }
554
555 bool SVGElement::haveLoadedRequiredResources()
556 {
557     for (auto& child : childrenOfType<SVGElement>(*this)) {
558         if (!child.haveLoadedRequiredResources())
559             return false;
560     }
561     return true;
562 }
563
564 bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> prpListener, bool useCapture)
565 {
566     RefPtr<EventListener> listener = prpListener;
567     
568     // Add event listener to regular DOM element
569     if (!Node::addEventListener(eventType, listener, useCapture))
570         return false;
571
572     if (containingShadowRoot())
573         return true;
574
575     // Add event listener to all shadow tree DOM element instances
576     ASSERT(!instanceUpdatesBlocked());
577     for (auto& instance : instancesForElement()) {
578         ASSERT(instance->shadowTreeElement());
579         ASSERT(instance->correspondingElement() == this);
580
581         bool result = instance->shadowTreeElement()->Node::addEventListener(eventType, listener, useCapture);
582         ASSERT_UNUSED(result, result);
583     }
584
585     return true;
586 }
587
588 bool SVGElement::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
589 {
590     if (containingShadowRoot())
591         return Node::removeEventListener(eventType, listener, useCapture);
592
593     // EventTarget::removeEventListener creates a PassRefPtr around the given EventListener
594     // object when creating a temporary RegisteredEventListener object used to look up the
595     // event listener in a cache. If we want to be able to call removeEventListener() multiple
596     // times on different nodes, we have to delay its immediate destruction, which would happen
597     // after the first call below.
598     RefPtr<EventListener> protector(listener);
599
600     // Remove event listener from regular DOM element
601     if (!Node::removeEventListener(eventType, listener, useCapture))
602         return false;
603
604     // Remove event listener from all shadow tree DOM element instances
605     ASSERT(!instanceUpdatesBlocked());
606     for (auto& instance : instancesForElement()) {
607         ASSERT(instance->correspondingElement() == this);
608
609         SVGElement* shadowTreeElement = instance->shadowTreeElement();
610         ASSERT(shadowTreeElement);
611
612         if (shadowTreeElement->Node::removeEventListener(eventType, listener, useCapture))
613             continue;
614
615         // This case can only be hit for event listeners created from markup
616         ASSERT(listener->wasCreatedFromMarkup());
617
618         // If the event listener 'listener' has been created from markup and has been fired before
619         // then JSLazyEventListener::parseCode() has been called and m_jsFunction of that listener
620         // has been created (read: it's not 0 anymore). During shadow tree creation, the event
621         // listener DOM attribute has been cloned, and another event listener has been setup in
622         // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
623         // and tryRemoveEventListener() above will fail. Work around that very seldom problem.
624         EventTargetData* data = shadowTreeElement->eventTargetData();
625         ASSERT(data);
626
627         data->eventListenerMap.removeFirstEventListenerCreatedFromMarkup(eventType);
628     }
629
630     return true;
631 }
632
633 static bool hasLoadListener(Element* element)
634 {
635     if (element->hasEventListeners(eventNames().loadEvent))
636         return true;
637
638     for (element = element->parentOrShadowHostElement(); element; element = element->parentOrShadowHostElement()) {
639         const EventListenerVector& entry = element->getEventListeners(eventNames().loadEvent);
640         for (size_t i = 0; i < entry.size(); ++i) {
641             if (entry[i].useCapture)
642                 return true;
643         }
644     }
645
646     return false;
647 }
648
649 #if ENABLE(CSS_REGIONS)
650 bool SVGElement::shouldMoveToFlowThread(const RenderStyle& styleToUse) const
651 {
652     // Allow only svg root elements to be directly collected by a render flow thread.
653     return parentNode() && !parentNode()->isSVGElement() && hasTagName(SVGNames::svgTag) && Element::shouldMoveToFlowThread(styleToUse);
654 }
655 #endif
656
657 void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents)
658 {
659     RefPtr<SVGElement> currentTarget = this;
660     while (currentTarget && currentTarget->haveLoadedRequiredResources()) {
661         RefPtr<Element> parent;
662         if (sendParentLoadEvents)
663             parent = currentTarget->parentOrShadowHostElement(); // save the next parent to dispatch too incase dispatching the event changes the tree
664         if (hasLoadListener(currentTarget.get()))
665             currentTarget->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
666         currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : RefPtr<SVGElement>();
667         SVGElement* element = currentTarget.get();
668         if (!element || !element->isOutermostSVGSVGElement())
669             continue;
670
671         // Consider <svg onload="foo()"><image xlink:href="foo.png" externalResourcesRequired="true"/></svg>.
672         // If foo.png is not yet loaded, the first SVGLoad event will go to the <svg> element, sent through
673         // Document::implicitClose(). Then the SVGLoad event will fire for <image>, once its loaded.
674         ASSERT(sendParentLoadEvents);
675
676         // If the load event was not sent yet by Document::implicitClose(), but the <image> from the example
677         // above, just appeared, don't send the SVGLoad event to the outermost <svg>, but wait for the document
678         // to be "ready to render", first.
679         if (!document().loadEventFinished())
680             break;
681     }
682 }
683
684 void SVGElement::sendSVGLoadEventIfPossibleAsynchronously()
685 {
686     svgLoadEventTimer()->startOneShot(0);
687 }
688
689 void SVGElement::svgLoadEventTimerFired()
690 {
691     sendSVGLoadEventIfPossible();
692 }
693
694 Timer* SVGElement::svgLoadEventTimer()
695 {
696     ASSERT_NOT_REACHED();
697     return 0;
698 }
699
700 void SVGElement::finishParsingChildren()
701 {
702     StyledElement::finishParsingChildren();
703
704     // The outermost SVGSVGElement SVGLoad event is fired through Document::dispatchWindowLoadEvent.
705     if (isOutermostSVGSVGElement())
706         return;
707
708     // finishParsingChildren() is called when the close tag is reached for an element (e.g. </svg>)
709     // we send SVGLoad events here if we can, otherwise they'll be sent when any required loads finish
710     sendSVGLoadEventIfPossible();
711 }
712
713 bool SVGElement::childShouldCreateRenderer(const Node& child) const
714 {
715     static NeverDestroyed<HashSet<QualifiedName>> invalidTextContent;
716
717     if (invalidTextContent.get().isEmpty()) {
718         invalidTextContent.get().add(SVGNames::textPathTag);
719 #if ENABLE(SVG_FONTS)
720         invalidTextContent.get().add(SVGNames::altGlyphTag);
721 #endif
722         invalidTextContent.get().add(SVGNames::trefTag);
723         invalidTextContent.get().add(SVGNames::tspanTag);
724     }
725     if (child.isSVGElement()) {
726         const SVGElement& svgChild = downcast<SVGElement>(child);
727         if (invalidTextContent.get().contains(svgChild.tagQName()))
728             return false;
729
730         return svgChild.isValid();
731     }
732     return false;
733 }
734
735 void SVGElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
736 {
737     StyledElement::attributeChanged(name, oldValue, newValue);
738
739     if (name == HTMLNames::idAttr)
740         document().accessSVGExtensions().rebuildAllElementReferencesForTarget(*this);
741
742     // Changes to the style attribute are processed lazily (see Element::getAttribute() and related methods),
743     // so we don't want changes to the style attribute to result in extra work here.
744     if (name != HTMLNames::styleAttr)
745         svgAttributeChanged(name);
746 }
747
748 void SVGElement::synchronizeAllAnimatedSVGAttribute(SVGElement* svgElement)
749 {
750     ASSERT(svgElement->elementData());
751     ASSERT(svgElement->elementData()->animatedSVGAttributesAreDirty());
752
753     svgElement->localAttributeToPropertyMap().synchronizeProperties(svgElement);
754     svgElement->elementData()->setAnimatedSVGAttributesAreDirty(false);
755 }
756
757 void SVGElement::synchronizeAnimatedSVGAttribute(const QualifiedName& name) const
758 {
759     if (!elementData() || !elementData()->animatedSVGAttributesAreDirty())
760         return;
761
762     SVGElement* nonConstThis = const_cast<SVGElement*>(this);
763     if (name == anyQName())
764         synchronizeAllAnimatedSVGAttribute(nonConstThis);
765     else
766         nonConstThis->localAttributeToPropertyMap().synchronizeProperty(nonConstThis, name);
767 }
768
769 void SVGElement::synchronizeRequiredFeatures(SVGElement* contextElement)
770 {
771     ASSERT(contextElement);
772     contextElement->synchronizeRequiredFeatures();
773 }
774
775 void SVGElement::synchronizeRequiredExtensions(SVGElement* contextElement)
776 {
777     ASSERT(contextElement);
778     contextElement->synchronizeRequiredExtensions();
779 }
780
781 void SVGElement::synchronizeSystemLanguage(SVGElement* contextElement)
782 {
783     ASSERT(contextElement);
784     contextElement->synchronizeSystemLanguage();
785 }
786
787 PassRefPtr<RenderStyle> SVGElement::customStyleForRenderer(RenderStyle& parentStyle)
788 {
789     if (!correspondingElement())
790         return document().ensureStyleResolver().styleForElement(this, &parentStyle);
791
792     return document().ensureStyleResolver().styleForElement(correspondingElement(), &parentStyle, DisallowStyleSharing);
793 }
794
795 MutableStyleProperties* SVGElement::animatedSMILStyleProperties() const
796 {
797     if (m_svgRareData)
798         return m_svgRareData->animatedSMILStyleProperties();
799     return 0;
800 }
801
802 MutableStyleProperties& SVGElement::ensureAnimatedSMILStyleProperties()
803 {
804     return ensureSVGRareData().ensureAnimatedSMILStyleProperties();
805 }
806
807 void SVGElement::setUseOverrideComputedStyle(bool value)
808 {
809     if (m_svgRareData)
810         m_svgRareData->setUseOverrideComputedStyle(value);
811 }
812
813 RenderStyle* SVGElement::computedStyle(PseudoId pseudoElementSpecifier)
814 {
815     if (!m_svgRareData || !m_svgRareData->useOverrideComputedStyle())
816         return Element::computedStyle(pseudoElementSpecifier);
817
818     RenderStyle* parentStyle = nullptr;
819     if (Element* parent = parentOrShadowHostElement()) {
820         if (auto renderer = parent->renderer())
821             parentStyle = &renderer->style();
822     }
823
824     return m_svgRareData->overrideComputedStyle(this, parentStyle);
825 }
826
827 static void addQualifiedName(HashMap<AtomicString, QualifiedName>& map, const QualifiedName& name)
828 {
829     HashMap<AtomicString, QualifiedName>::AddResult addResult = map.add(name.localName(), name);
830     ASSERT_UNUSED(addResult, addResult.isNewEntry);
831 }
832
833 QualifiedName SVGElement::animatableAttributeForName(const AtomicString& localName)
834 {
835     static NeverDestroyed<HashMap<AtomicString, QualifiedName>> neverDestroyedAnimatableAttributes;
836     HashMap<AtomicString, QualifiedName>& animatableAttributes = neverDestroyedAnimatableAttributes;
837
838     if (animatableAttributes.isEmpty()) {
839         addQualifiedName(animatableAttributes, HTMLNames::classAttr);
840         addQualifiedName(animatableAttributes, SVGNames::amplitudeAttr);
841         addQualifiedName(animatableAttributes, SVGNames::azimuthAttr);
842         addQualifiedName(animatableAttributes, SVGNames::baseFrequencyAttr);
843         addQualifiedName(animatableAttributes, SVGNames::biasAttr);
844         addQualifiedName(animatableAttributes, SVGNames::clipPathUnitsAttr);
845         addQualifiedName(animatableAttributes, SVGNames::cxAttr);
846         addQualifiedName(animatableAttributes, SVGNames::cyAttr);
847         addQualifiedName(animatableAttributes, SVGNames::diffuseConstantAttr);
848         addQualifiedName(animatableAttributes, SVGNames::divisorAttr);
849         addQualifiedName(animatableAttributes, SVGNames::dxAttr);
850         addQualifiedName(animatableAttributes, SVGNames::dyAttr);
851         addQualifiedName(animatableAttributes, SVGNames::edgeModeAttr);
852         addQualifiedName(animatableAttributes, SVGNames::elevationAttr);
853         addQualifiedName(animatableAttributes, SVGNames::exponentAttr);
854         addQualifiedName(animatableAttributes, SVGNames::externalResourcesRequiredAttr);
855         addQualifiedName(animatableAttributes, SVGNames::filterResAttr);
856         addQualifiedName(animatableAttributes, SVGNames::filterUnitsAttr);
857         addQualifiedName(animatableAttributes, SVGNames::fxAttr);
858         addQualifiedName(animatableAttributes, SVGNames::fyAttr);
859         addQualifiedName(animatableAttributes, SVGNames::gradientTransformAttr);
860         addQualifiedName(animatableAttributes, SVGNames::gradientUnitsAttr);
861         addQualifiedName(animatableAttributes, SVGNames::heightAttr);
862         addQualifiedName(animatableAttributes, SVGNames::in2Attr);
863         addQualifiedName(animatableAttributes, SVGNames::inAttr);
864         addQualifiedName(animatableAttributes, SVGNames::interceptAttr);
865         addQualifiedName(animatableAttributes, SVGNames::k1Attr);
866         addQualifiedName(animatableAttributes, SVGNames::k2Attr);
867         addQualifiedName(animatableAttributes, SVGNames::k3Attr);
868         addQualifiedName(animatableAttributes, SVGNames::k4Attr);
869         addQualifiedName(animatableAttributes, SVGNames::kernelMatrixAttr);
870         addQualifiedName(animatableAttributes, SVGNames::kernelUnitLengthAttr);
871         addQualifiedName(animatableAttributes, SVGNames::lengthAdjustAttr);
872         addQualifiedName(animatableAttributes, SVGNames::limitingConeAngleAttr);
873         addQualifiedName(animatableAttributes, SVGNames::markerHeightAttr);
874         addQualifiedName(animatableAttributes, SVGNames::markerUnitsAttr);
875         addQualifiedName(animatableAttributes, SVGNames::markerWidthAttr);
876         addQualifiedName(animatableAttributes, SVGNames::maskContentUnitsAttr);
877         addQualifiedName(animatableAttributes, SVGNames::maskUnitsAttr);
878         addQualifiedName(animatableAttributes, SVGNames::methodAttr);
879         addQualifiedName(animatableAttributes, SVGNames::modeAttr);
880         addQualifiedName(animatableAttributes, SVGNames::numOctavesAttr);
881         addQualifiedName(animatableAttributes, SVGNames::offsetAttr);
882         addQualifiedName(animatableAttributes, SVGNames::operatorAttr);
883         addQualifiedName(animatableAttributes, SVGNames::orderAttr);
884         addQualifiedName(animatableAttributes, SVGNames::orientAttr);
885         addQualifiedName(animatableAttributes, SVGNames::pathLengthAttr);
886         addQualifiedName(animatableAttributes, SVGNames::patternContentUnitsAttr);
887         addQualifiedName(animatableAttributes, SVGNames::patternTransformAttr);
888         addQualifiedName(animatableAttributes, SVGNames::patternUnitsAttr);
889         addQualifiedName(animatableAttributes, SVGNames::pointsAtXAttr);
890         addQualifiedName(animatableAttributes, SVGNames::pointsAtYAttr);
891         addQualifiedName(animatableAttributes, SVGNames::pointsAtZAttr);
892         addQualifiedName(animatableAttributes, SVGNames::preserveAlphaAttr);
893         addQualifiedName(animatableAttributes, SVGNames::preserveAspectRatioAttr);
894         addQualifiedName(animatableAttributes, SVGNames::primitiveUnitsAttr);
895         addQualifiedName(animatableAttributes, SVGNames::radiusAttr);
896         addQualifiedName(animatableAttributes, SVGNames::rAttr);
897         addQualifiedName(animatableAttributes, SVGNames::refXAttr);
898         addQualifiedName(animatableAttributes, SVGNames::refYAttr);
899         addQualifiedName(animatableAttributes, SVGNames::resultAttr);
900         addQualifiedName(animatableAttributes, SVGNames::rotateAttr);
901         addQualifiedName(animatableAttributes, SVGNames::rxAttr);
902         addQualifiedName(animatableAttributes, SVGNames::ryAttr);
903         addQualifiedName(animatableAttributes, SVGNames::scaleAttr);
904         addQualifiedName(animatableAttributes, SVGNames::seedAttr);
905         addQualifiedName(animatableAttributes, SVGNames::slopeAttr);
906         addQualifiedName(animatableAttributes, SVGNames::spacingAttr);
907         addQualifiedName(animatableAttributes, SVGNames::specularConstantAttr);
908         addQualifiedName(animatableAttributes, SVGNames::specularExponentAttr);
909         addQualifiedName(animatableAttributes, SVGNames::spreadMethodAttr);
910         addQualifiedName(animatableAttributes, SVGNames::startOffsetAttr);
911         addQualifiedName(animatableAttributes, SVGNames::stdDeviationAttr);
912         addQualifiedName(animatableAttributes, SVGNames::stitchTilesAttr);
913         addQualifiedName(animatableAttributes, SVGNames::surfaceScaleAttr);
914         addQualifiedName(animatableAttributes, SVGNames::tableValuesAttr);
915         addQualifiedName(animatableAttributes, SVGNames::targetAttr);
916         addQualifiedName(animatableAttributes, SVGNames::targetXAttr);
917         addQualifiedName(animatableAttributes, SVGNames::targetYAttr);
918         addQualifiedName(animatableAttributes, SVGNames::transformAttr);
919         addQualifiedName(animatableAttributes, SVGNames::typeAttr);
920         addQualifiedName(animatableAttributes, SVGNames::valuesAttr);
921         addQualifiedName(animatableAttributes, SVGNames::viewBoxAttr);
922         addQualifiedName(animatableAttributes, SVGNames::widthAttr);
923         addQualifiedName(animatableAttributes, SVGNames::x1Attr);
924         addQualifiedName(animatableAttributes, SVGNames::x2Attr);
925         addQualifiedName(animatableAttributes, SVGNames::xAttr);
926         addQualifiedName(animatableAttributes, SVGNames::xChannelSelectorAttr);
927         addQualifiedName(animatableAttributes, SVGNames::y1Attr);
928         addQualifiedName(animatableAttributes, SVGNames::y2Attr);
929         addQualifiedName(animatableAttributes, SVGNames::yAttr);
930         addQualifiedName(animatableAttributes, SVGNames::yChannelSelectorAttr);
931         addQualifiedName(animatableAttributes, SVGNames::zAttr);
932         addQualifiedName(animatableAttributes, XLinkNames::hrefAttr);
933     }
934     return animatableAttributes.get(localName);
935 }
936
937 #ifndef NDEBUG
938 bool SVGElement::isAnimatableAttribute(const QualifiedName& name) const
939 {
940     if (SVGElement::animatableAttributeForName(name.localName()) == name)
941         return !filterOutAnimatableAttribute(name);
942     return false;
943 }
944
945 bool SVGElement::filterOutAnimatableAttribute(const QualifiedName&) const
946 {
947     return false;
948 }
949 #endif
950
951 String SVGElement::title() const
952 {
953     // According to spec, we should not return titles when hovering over root <svg> elements (those
954     // <title> elements are the title of the document, not a tooltip) so we instantly return.
955     if (isOutermostSVGSVGElement())
956         return String();
957
958     // Walk up the tree, to find out whether we're inside a <use> shadow tree, to find the right title.
959     if (isInShadowTree()) {
960         Element* shadowHostElement = downcast<ShadowRoot>(treeScope().rootNode()).hostElement();
961         // At this time, SVG nodes are not allowed in non-<use> shadow trees, so any shadow root we do
962         // have should be a use. The assert and following test is here to catch future shadow DOM changes
963         // that do enable SVG in a shadow tree.
964         ASSERT(!shadowHostElement || shadowHostElement->hasTagName(SVGNames::useTag));
965         if (shadowHostElement && shadowHostElement->hasTagName(SVGNames::useTag)) {
966             SVGUseElement& useElement = downcast<SVGUseElement>(*shadowHostElement);
967
968             // If the <use> title is not empty we found the title to use.
969             String useTitle(useElement.title());
970             if (!useTitle.isEmpty())
971                 return useTitle;
972         }
973     }
974
975     // If we aren't an instance in a <use> or the <use> title was not found, then find the first
976     // <title> child of this element.
977     auto firstTitle = descendantsOfType<SVGTitleElement>(*this).first();
978     return firstTitle ? const_cast<SVGTitleElement*>(firstTitle)->innerText() : String();
979 }
980
981 bool SVGElement::rendererIsNeeded(const RenderStyle& style)
982 {
983     // http://www.w3.org/TR/SVG/extend.html#PrivateData
984     // Prevent anything other than SVG renderers from appearing in our render tree
985     // Spec: SVG allows inclusion of elements from foreign namespaces anywhere
986     // with the SVG content. In general, the SVG user agent will include the unknown
987     // elements in the DOM but will otherwise ignore unknown elements.
988     if (!parentOrShadowHostElement() || parentOrShadowHostElement()->isSVGElement())
989         return StyledElement::rendererIsNeeded(style);
990
991     return false;
992 }
993
994 CSSPropertyID SVGElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName)
995 {
996     if (!attrName.namespaceURI().isNull())
997         return CSSPropertyInvalid;
998
999     static NeverDestroyed<HashMap<AtomicStringImpl*, CSSPropertyID>> properties;
1000     if (properties.get().isEmpty())
1001         populateAttributeNameToCSSPropertyIDMap(properties.get());
1002
1003     return properties.get().get(attrName.localName().impl());
1004 }
1005
1006 bool SVGElement::isAnimatableCSSProperty(const QualifiedName& attributeName)
1007 {
1008     return attributeNameToAnimatedPropertyTypeMap().contains(attributeName.impl())
1009         || cssPropertyWithSVGDOMNameToAnimatedPropertyTypeMap().contains(attributeName.impl());
1010 }
1011
1012 bool SVGElement::isPresentationAttributeWithSVGDOM(const QualifiedName& attributeName)
1013 {
1014     Vector<AnimatedPropertyType> propertyTypes;
1015     localAttributeToPropertyMap().animatedPropertyTypeForAttribute(attributeName, propertyTypes);
1016     return !propertyTypes.isEmpty();
1017 }
1018
1019 bool SVGElement::isPresentationAttribute(const QualifiedName& name) const
1020 {
1021     if (cssPropertyIdForSVGAttributeName(name) > 0)
1022         return true;
1023     return StyledElement::isPresentationAttribute(name);
1024 }
1025
1026 void SVGElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
1027 {
1028     CSSPropertyID propertyID = cssPropertyIdForSVGAttributeName(name);
1029     if (propertyID > 0)
1030         addPropertyToPresentationAttributeStyle(style, propertyID, value);
1031 }
1032
1033 bool SVGElement::isKnownAttribute(const QualifiedName& attrName)
1034 {
1035     return attrName == HTMLNames::idAttr;
1036 }
1037
1038 void SVGElement::svgAttributeChanged(const QualifiedName& attrName)
1039 {
1040     CSSPropertyID propId = cssPropertyIdForSVGAttributeName(attrName);
1041     if (propId > 0) {
1042         SVGElementInstance::invalidateAllInstancesOfElement(this);
1043         return;
1044     }
1045
1046     if (attrName == HTMLNames::classAttr) {
1047         classAttributeChanged(className());
1048         SVGElementInstance::invalidateAllInstancesOfElement(this);
1049         return;
1050     }
1051
1052     if (attrName == HTMLNames::idAttr) {
1053         auto renderer = this->renderer();
1054         // Notify resources about id changes, this is important as we cache resources by id in SVGDocumentExtensions
1055         if (is<RenderSVGResourceContainer>(renderer))
1056             downcast<RenderSVGResourceContainer>(*renderer).idChanged();
1057         if (inDocument())
1058             buildPendingResourcesIfNeeded();
1059         SVGElementInstance::invalidateAllInstancesOfElement(this);
1060         return;
1061     }
1062 }
1063
1064 Node::InsertionNotificationRequest SVGElement::insertedInto(ContainerNode& rootParent)
1065 {
1066     StyledElement::insertedInto(rootParent);
1067     updateRelativeLengthsInformation();
1068     buildPendingResourcesIfNeeded();
1069     return InsertionDone;
1070 }
1071
1072 void SVGElement::buildPendingResourcesIfNeeded()
1073 {
1074     if (!needsPendingResourceHandling() || !inDocument() || isInShadowTree())
1075         return;
1076
1077     SVGDocumentExtensions& extensions = document().accessSVGExtensions();
1078     String resourceId = getIdAttribute();
1079     if (!extensions.isIdOfPendingResource(resourceId))
1080         return;
1081
1082     // Mark pending resources as pending for removal.
1083     extensions.markPendingResourcesForRemoval(resourceId);
1084
1085     // Rebuild pending resources for each client of a pending resource that is being removed.
1086     while (Element* clientElement = extensions.removeElementFromPendingResourcesForRemovalMap(resourceId)) {
1087         ASSERT(clientElement->hasPendingResources());
1088         if (clientElement->hasPendingResources()) {
1089             clientElement->buildPendingResource();
1090             extensions.clearHasPendingResourcesIfPossible(clientElement);
1091         }
1092     }
1093 }
1094
1095 void SVGElement::childrenChanged(const ChildChange& change)
1096 {
1097     StyledElement::childrenChanged(change);
1098
1099     if (change.source == ChildChangeSourceParser)
1100         return;
1101     SVGElementInstance::invalidateAllInstancesOfElement(this);
1102 }
1103
1104 PassRefPtr<CSSValue> SVGElement::getPresentationAttribute(const String& name)
1105 {
1106     if (!hasAttributesWithoutUpdate())
1107         return 0;
1108
1109     QualifiedName attributeName(nullAtom, name, nullAtom);
1110     const Attribute* attribute = findAttributeByName(attributeName);
1111     if (!attribute)
1112         return 0;
1113
1114     RefPtr<MutableStyleProperties> style = MutableStyleProperties::create(SVGAttributeMode);
1115     CSSPropertyID propertyID = cssPropertyIdForSVGAttributeName(attribute->name());
1116     style->setProperty(propertyID, attribute->value());
1117     RefPtr<CSSValue> cssValue = style->getPropertyCSSValue(propertyID);
1118     return cssValue ? cssValue->cloneForCSSOM() : 0;
1119 }
1120
1121 bool SVGElement::instanceUpdatesBlocked() const
1122 {
1123     return m_svgRareData && m_svgRareData->instanceUpdatesBlocked();
1124 }
1125
1126 void SVGElement::setInstanceUpdatesBlocked(bool value)
1127 {
1128     if (m_svgRareData)
1129         m_svgRareData->setInstanceUpdatesBlocked(value);
1130 }
1131
1132 AffineTransform SVGElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const
1133 {
1134     // To be overriden by SVGGraphicsElement (or as special case SVGTextElement and SVGPatternElement)
1135     return AffineTransform();
1136 }
1137
1138 void SVGElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement* element)
1139 {
1140     // If we're not yet in a document, this function will be called again from insertedInto(). Do nothing now.
1141     if (!inDocument())
1142         return;
1143
1144     // An element wants to notify us that its own relative lengths state changed.
1145     // Register it in the relative length map, and register us in the parent relative length map.
1146     // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.
1147
1148     if (hasRelativeLengths)
1149         m_elementsWithRelativeLengths.add(element);
1150     else {
1151         if (!m_elementsWithRelativeLengths.contains(element)) {
1152             // We were never registered. Do nothing.
1153             return;
1154         }
1155
1156         m_elementsWithRelativeLengths.remove(element);
1157     }
1158
1159     if (!element->isSVGGraphicsElement())
1160         return;
1161
1162     // Find first styled parent node, and notify it that we've changed our relative length state.
1163     ContainerNode* node = parentNode();
1164     while (node) {
1165         if (!node->isSVGElement())
1166             break;
1167
1168         // Register us in the parent element map.
1169         downcast<SVGElement>(*node).updateRelativeLengthsInformation(hasRelativeLengths, this);
1170         break;
1171     }
1172 }
1173
1174 bool SVGElement::hasFocusEventListeners() const
1175 {
1176     Element* eventTarget = const_cast<SVGElement*>(this);
1177     return eventTarget->hasEventListeners(eventNames().focusinEvent)
1178         || eventTarget->hasEventListeners(eventNames().focusoutEvent)
1179         || eventTarget->hasEventListeners(eventNames().focusEvent)
1180         || eventTarget->hasEventListeners(eventNames().blurEvent);
1181 }
1182
1183 bool SVGElement::isMouseFocusable() const
1184 {
1185     if (!isFocusable())
1186         return false;
1187     Element* eventTarget = const_cast<SVGElement*>(this);
1188     return hasFocusEventListeners()
1189         || eventTarget->hasEventListeners(eventNames().keydownEvent)
1190         || eventTarget->hasEventListeners(eventNames().keyupEvent)
1191         || eventTarget->hasEventListeners(eventNames().keypressEvent);
1192 }
1193     
1194 void SVGElement::accessKeyAction(bool sendMouseEvents)
1195 {
1196     dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
1197 }
1198
1199 }