• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 
4     This file is part of the KDE project
5 
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10 
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15 
16     You should have received a copy of the GNU Library General Public License
17     along with this library; see the file COPYING.LIB.  If not, write to
18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19     Boston, MA 02110-1301, USA.
20 */
21 
22 #include "config.h"
23 
24 #if ENABLE(SVG)
25 #include "SVGElementInstance.h"
26 
27 #include "ContainerNodeAlgorithms.h"
28 #include "Document.h"
29 #include "Event.h"
30 #include "EventException.h"
31 #include "EventListener.h"
32 #include "EventNames.h"
33 #include "FrameView.h"
34 #include "SVGElementInstanceList.h"
35 #include "SVGUseElement.h"
36 
37 #include <wtf/RefCountedLeakCounter.h>
38 
39 #if USE(JSC)
40 #include "GCController.h"
41 #endif
42 
43 namespace WebCore {
44 
45 #ifndef NDEBUG
46 static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance");
47 #endif
48 
SVGElementInstance(SVGUseElement * useElement,SVGElement * originalElement)49 SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement)
50     : m_needsUpdate(false)
51     , m_useElement(useElement)
52     , m_element(originalElement)
53     , m_previousSibling(0)
54     , m_nextSibling(0)
55     , m_firstChild(0)
56     , m_lastChild(0)
57 {
58     ASSERT(m_useElement);
59     ASSERT(m_element);
60 
61     // Register as instance for passed element.
62     m_element->mapInstanceToElement(this);
63 
64 #ifndef NDEBUG
65     instanceCounter.increment();
66 #endif
67 }
68 
~SVGElementInstance()69 SVGElementInstance::~SVGElementInstance()
70 {
71 #ifndef NDEBUG
72     instanceCounter.decrement();
73 #endif
74 
75     // Deregister as instance for passed element.
76     m_element->removeInstanceMapping(this);
77 
78     removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
79 }
80 
childNodes()81 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
82 {
83     return SVGElementInstanceList::create(this);
84 }
85 
setShadowTreeElement(SVGElement * element)86 void SVGElementInstance::setShadowTreeElement(SVGElement* element)
87 {
88     ASSERT(element);
89     m_shadowTreeElement = element;
90 }
91 
forgetWrapper()92 void SVGElementInstance::forgetWrapper()
93 {
94 #if USE(JSC)
95     // FIXME: This is fragile, as discussed with Sam. Need to find a better solution.
96     // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;".
97     // We still have to recreate this wrapper somehow. The gc collection below, won't catch it.
98 
99     // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects
100     // are still holding RefPtrs of SVGElementInstance objects, which prevent us to
101     // be deleted (and the shadow tree is not destructed as well). Force JS GC.
102     gcController().garbageCollectNow();
103 #endif
104 }
105 
appendChild(PassRefPtr<SVGElementInstance> child)106 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
107 {
108     appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
109 }
110 
invalidateAllInstancesOfElement(SVGElement * element)111 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
112 {
113     if (!element)
114         return;
115 
116     HashSet<SVGElementInstance*> set = element->instancesForElement();
117     if (set.isEmpty())
118         return;
119 
120     // Find all use elements referencing the instances - ask them _once_ to rebuild.
121     HashSet<SVGElementInstance*>::const_iterator it = set.begin();
122     const HashSet<SVGElementInstance*>::const_iterator end = set.end();
123 
124     for (; it != end; ++it)
125         (*it)->setNeedsUpdate(true);
126 }
127 
setNeedsUpdate(bool value)128 void SVGElementInstance::setNeedsUpdate(bool value)
129 {
130     m_needsUpdate = value;
131 
132     if (m_needsUpdate)
133         correspondingUseElement()->setNeedsStyleRecalc();
134 }
135 
scriptExecutionContext() const136 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const
137 {
138     if (SVGElement* element = correspondingElement())
139         return element->document();
140     return 0;
141 }
142 
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)143 void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
144 {
145     if (SVGElement* element = correspondingElement())
146         element->addEventListener(eventType, listener, useCapture);
147 }
148 
removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)149 void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
150 {
151     if (SVGElement* element = correspondingElement())
152         element->removeEventListener(eventType, listener, useCapture);
153 }
154 
dispatchEvent(PassRefPtr<Event> e,ExceptionCode & ec)155 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec)
156 {
157     RefPtr<Event> evt(e);
158     ASSERT(!eventDispatchForbidden());
159     if (!evt || evt->type().isEmpty()) {
160         ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
161         return false;
162     }
163 
164     // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()!
165     SVGElement* element = shadowTreeElement();
166     if (!element)
167         return false;
168 
169     evt->setTarget(this);
170 
171     RefPtr<FrameView> view = element->document()->view();
172     return element->dispatchGenericEvent(evt.release());
173 }
174 
onabort() const175 EventListener* SVGElementInstance::onabort() const
176 {
177     return correspondingElement()->getAttributeEventListener(eventNames().abortEvent);
178 }
179 
setOnabort(PassRefPtr<EventListener> eventListener)180 void SVGElementInstance::setOnabort(PassRefPtr<EventListener> eventListener)
181 {
182     correspondingElement()->setAttributeEventListener(eventNames().abortEvent, eventListener);
183 }
184 
onblur() const185 EventListener* SVGElementInstance::onblur() const
186 {
187     return correspondingElement()->getAttributeEventListener(eventNames().blurEvent);
188 }
189 
setOnblur(PassRefPtr<EventListener> eventListener)190 void SVGElementInstance::setOnblur(PassRefPtr<EventListener> eventListener)
191 {
192     correspondingElement()->setAttributeEventListener(eventNames().blurEvent, eventListener);
193 }
194 
onchange() const195 EventListener* SVGElementInstance::onchange() const
196 {
197     return correspondingElement()->getAttributeEventListener(eventNames().changeEvent);
198 }
199 
setOnchange(PassRefPtr<EventListener> eventListener)200 void SVGElementInstance::setOnchange(PassRefPtr<EventListener> eventListener)
201 {
202     correspondingElement()->setAttributeEventListener(eventNames().changeEvent, eventListener);
203 }
204 
onclick() const205 EventListener* SVGElementInstance::onclick() const
206 {
207     return correspondingElement()->getAttributeEventListener(eventNames().clickEvent);
208 }
209 
setOnclick(PassRefPtr<EventListener> eventListener)210 void SVGElementInstance::setOnclick(PassRefPtr<EventListener> eventListener)
211 {
212     correspondingElement()->setAttributeEventListener(eventNames().clickEvent, eventListener);
213 }
214 
oncontextmenu() const215 EventListener* SVGElementInstance::oncontextmenu() const
216 {
217     return correspondingElement()->getAttributeEventListener(eventNames().contextmenuEvent);
218 }
219 
setOncontextmenu(PassRefPtr<EventListener> eventListener)220 void SVGElementInstance::setOncontextmenu(PassRefPtr<EventListener> eventListener)
221 {
222     correspondingElement()->setAttributeEventListener(eventNames().contextmenuEvent, eventListener);
223 }
224 
ondblclick() const225 EventListener* SVGElementInstance::ondblclick() const
226 {
227     return correspondingElement()->getAttributeEventListener(eventNames().dblclickEvent);
228 }
229 
setOndblclick(PassRefPtr<EventListener> eventListener)230 void SVGElementInstance::setOndblclick(PassRefPtr<EventListener> eventListener)
231 {
232     correspondingElement()->setAttributeEventListener(eventNames().dblclickEvent, eventListener);
233 }
234 
onerror() const235 EventListener* SVGElementInstance::onerror() const
236 {
237     return correspondingElement()->getAttributeEventListener(eventNames().errorEvent);
238 }
239 
setOnerror(PassRefPtr<EventListener> eventListener)240 void SVGElementInstance::setOnerror(PassRefPtr<EventListener> eventListener)
241 {
242     correspondingElement()->setAttributeEventListener(eventNames().errorEvent, eventListener);
243 }
244 
onfocus() const245 EventListener* SVGElementInstance::onfocus() const
246 {
247     return correspondingElement()->getAttributeEventListener(eventNames().focusEvent);
248 }
249 
setOnfocus(PassRefPtr<EventListener> eventListener)250 void SVGElementInstance::setOnfocus(PassRefPtr<EventListener> eventListener)
251 {
252     correspondingElement()->setAttributeEventListener(eventNames().focusEvent, eventListener);
253 }
254 
oninput() const255 EventListener* SVGElementInstance::oninput() const
256 {
257     return correspondingElement()->getAttributeEventListener(eventNames().inputEvent);
258 }
259 
setOninput(PassRefPtr<EventListener> eventListener)260 void SVGElementInstance::setOninput(PassRefPtr<EventListener> eventListener)
261 {
262     correspondingElement()->setAttributeEventListener(eventNames().inputEvent, eventListener);
263 }
264 
onkeydown() const265 EventListener* SVGElementInstance::onkeydown() const
266 {
267     return correspondingElement()->getAttributeEventListener(eventNames().keydownEvent);
268 }
269 
setOnkeydown(PassRefPtr<EventListener> eventListener)270 void SVGElementInstance::setOnkeydown(PassRefPtr<EventListener> eventListener)
271 {
272     correspondingElement()->setAttributeEventListener(eventNames().keydownEvent, eventListener);
273 }
274 
onkeypress() const275 EventListener* SVGElementInstance::onkeypress() const
276 {
277     return correspondingElement()->getAttributeEventListener(eventNames().keypressEvent);
278 }
279 
setOnkeypress(PassRefPtr<EventListener> eventListener)280 void SVGElementInstance::setOnkeypress(PassRefPtr<EventListener> eventListener)
281 {
282     correspondingElement()->setAttributeEventListener(eventNames().keypressEvent, eventListener);
283 }
284 
onkeyup() const285 EventListener* SVGElementInstance::onkeyup() const
286 {
287     return correspondingElement()->getAttributeEventListener(eventNames().keyupEvent);
288 }
289 
setOnkeyup(PassRefPtr<EventListener> eventListener)290 void SVGElementInstance::setOnkeyup(PassRefPtr<EventListener> eventListener)
291 {
292     correspondingElement()->setAttributeEventListener(eventNames().keyupEvent, eventListener);
293 }
294 
onload() const295 EventListener* SVGElementInstance::onload() const
296 {
297     return correspondingElement()->getAttributeEventListener(eventNames().loadEvent);
298 }
299 
setOnload(PassRefPtr<EventListener> eventListener)300 void SVGElementInstance::setOnload(PassRefPtr<EventListener> eventListener)
301 {
302     correspondingElement()->setAttributeEventListener(eventNames().loadEvent, eventListener);
303 }
304 
onmousedown() const305 EventListener* SVGElementInstance::onmousedown() const
306 {
307     return correspondingElement()->getAttributeEventListener(eventNames().mousedownEvent);
308 }
309 
setOnmousedown(PassRefPtr<EventListener> eventListener)310 void SVGElementInstance::setOnmousedown(PassRefPtr<EventListener> eventListener)
311 {
312     correspondingElement()->setAttributeEventListener(eventNames().mousedownEvent, eventListener);
313 }
314 
onmousemove() const315 EventListener* SVGElementInstance::onmousemove() const
316 {
317     return correspondingElement()->getAttributeEventListener(eventNames().mousemoveEvent);
318 }
319 
setOnmousemove(PassRefPtr<EventListener> eventListener)320 void SVGElementInstance::setOnmousemove(PassRefPtr<EventListener> eventListener)
321 {
322     correspondingElement()->setAttributeEventListener(eventNames().mousemoveEvent, eventListener);
323 }
324 
onmouseout() const325 EventListener* SVGElementInstance::onmouseout() const
326 {
327     return correspondingElement()->getAttributeEventListener(eventNames().mouseoutEvent);
328 }
329 
setOnmouseout(PassRefPtr<EventListener> eventListener)330 void SVGElementInstance::setOnmouseout(PassRefPtr<EventListener> eventListener)
331 {
332     correspondingElement()->setAttributeEventListener(eventNames().mouseoutEvent, eventListener);
333 }
334 
onmouseover() const335 EventListener* SVGElementInstance::onmouseover() const
336 {
337     return correspondingElement()->getAttributeEventListener(eventNames().mouseoverEvent);
338 }
339 
setOnmouseover(PassRefPtr<EventListener> eventListener)340 void SVGElementInstance::setOnmouseover(PassRefPtr<EventListener> eventListener)
341 {
342     correspondingElement()->setAttributeEventListener(eventNames().mouseoverEvent, eventListener);
343 }
344 
onmouseup() const345 EventListener* SVGElementInstance::onmouseup() const
346 {
347     return correspondingElement()->getAttributeEventListener(eventNames().mouseupEvent);
348 }
349 
setOnmouseup(PassRefPtr<EventListener> eventListener)350 void SVGElementInstance::setOnmouseup(PassRefPtr<EventListener> eventListener)
351 {
352     correspondingElement()->setAttributeEventListener(eventNames().mouseupEvent, eventListener);
353 }
354 
onmousewheel() const355 EventListener* SVGElementInstance::onmousewheel() const
356 {
357     return correspondingElement()->getAttributeEventListener(eventNames().mousewheelEvent);
358 }
359 
setOnmousewheel(PassRefPtr<EventListener> eventListener)360 void SVGElementInstance::setOnmousewheel(PassRefPtr<EventListener> eventListener)
361 {
362     correspondingElement()->setAttributeEventListener(eventNames().mousewheelEvent, eventListener);
363 }
364 
onbeforecut() const365 EventListener* SVGElementInstance::onbeforecut() const
366 {
367     return correspondingElement()->getAttributeEventListener(eventNames().beforecutEvent);
368 }
369 
setOnbeforecut(PassRefPtr<EventListener> eventListener)370 void SVGElementInstance::setOnbeforecut(PassRefPtr<EventListener> eventListener)
371 {
372     correspondingElement()->setAttributeEventListener(eventNames().beforecutEvent, eventListener);
373 }
374 
oncut() const375 EventListener* SVGElementInstance::oncut() const
376 {
377     return correspondingElement()->getAttributeEventListener(eventNames().cutEvent);
378 }
379 
setOncut(PassRefPtr<EventListener> eventListener)380 void SVGElementInstance::setOncut(PassRefPtr<EventListener> eventListener)
381 {
382     correspondingElement()->setAttributeEventListener(eventNames().cutEvent, eventListener);
383 }
384 
onbeforecopy() const385 EventListener* SVGElementInstance::onbeforecopy() const
386 {
387     return correspondingElement()->getAttributeEventListener(eventNames().beforecopyEvent);
388 }
389 
setOnbeforecopy(PassRefPtr<EventListener> eventListener)390 void SVGElementInstance::setOnbeforecopy(PassRefPtr<EventListener> eventListener)
391 {
392     correspondingElement()->setAttributeEventListener(eventNames().beforecopyEvent, eventListener);
393 }
394 
oncopy() const395 EventListener* SVGElementInstance::oncopy() const
396 {
397     return correspondingElement()->getAttributeEventListener(eventNames().copyEvent);
398 }
399 
setOncopy(PassRefPtr<EventListener> eventListener)400 void SVGElementInstance::setOncopy(PassRefPtr<EventListener> eventListener)
401 {
402     correspondingElement()->setAttributeEventListener(eventNames().copyEvent, eventListener);
403 }
404 
onbeforepaste() const405 EventListener* SVGElementInstance::onbeforepaste() const
406 {
407     return correspondingElement()->getAttributeEventListener(eventNames().beforepasteEvent);
408 }
409 
setOnbeforepaste(PassRefPtr<EventListener> eventListener)410 void SVGElementInstance::setOnbeforepaste(PassRefPtr<EventListener> eventListener)
411 {
412     correspondingElement()->setAttributeEventListener(eventNames().beforepasteEvent, eventListener);
413 }
414 
onpaste() const415 EventListener* SVGElementInstance::onpaste() const
416 {
417     return correspondingElement()->getAttributeEventListener(eventNames().pasteEvent);
418 }
419 
setOnpaste(PassRefPtr<EventListener> eventListener)420 void SVGElementInstance::setOnpaste(PassRefPtr<EventListener> eventListener)
421 {
422     correspondingElement()->setAttributeEventListener(eventNames().pasteEvent, eventListener);
423 }
424 
ondragenter() const425 EventListener* SVGElementInstance::ondragenter() const
426 {
427     return correspondingElement()->getAttributeEventListener(eventNames().dragenterEvent);
428 }
429 
setOndragenter(PassRefPtr<EventListener> eventListener)430 void SVGElementInstance::setOndragenter(PassRefPtr<EventListener> eventListener)
431 {
432     correspondingElement()->setAttributeEventListener(eventNames().dragenterEvent, eventListener);
433 }
434 
ondragover() const435 EventListener* SVGElementInstance::ondragover() const
436 {
437     return correspondingElement()->getAttributeEventListener(eventNames().dragoverEvent);
438 }
439 
setOndragover(PassRefPtr<EventListener> eventListener)440 void SVGElementInstance::setOndragover(PassRefPtr<EventListener> eventListener)
441 {
442     correspondingElement()->setAttributeEventListener(eventNames().dragoverEvent, eventListener);
443 }
444 
ondragleave() const445 EventListener* SVGElementInstance::ondragleave() const
446 {
447     return correspondingElement()->getAttributeEventListener(eventNames().dragleaveEvent);
448 }
449 
setOndragleave(PassRefPtr<EventListener> eventListener)450 void SVGElementInstance::setOndragleave(PassRefPtr<EventListener> eventListener)
451 {
452     correspondingElement()->setAttributeEventListener(eventNames().dragleaveEvent, eventListener);
453 }
454 
ondrop() const455 EventListener* SVGElementInstance::ondrop() const
456 {
457     return correspondingElement()->getAttributeEventListener(eventNames().dropEvent);
458 }
459 
setOndrop(PassRefPtr<EventListener> eventListener)460 void SVGElementInstance::setOndrop(PassRefPtr<EventListener> eventListener)
461 {
462     correspondingElement()->setAttributeEventListener(eventNames().dropEvent, eventListener);
463 }
464 
ondragstart() const465 EventListener* SVGElementInstance::ondragstart() const
466 {
467     return correspondingElement()->getAttributeEventListener(eventNames().dragstartEvent);
468 }
469 
setOndragstart(PassRefPtr<EventListener> eventListener)470 void SVGElementInstance::setOndragstart(PassRefPtr<EventListener> eventListener)
471 {
472     correspondingElement()->setAttributeEventListener(eventNames().dragstartEvent, eventListener);
473 }
474 
ondrag() const475 EventListener* SVGElementInstance::ondrag() const
476 {
477     return correspondingElement()->getAttributeEventListener(eventNames().dragEvent);
478 }
479 
setOndrag(PassRefPtr<EventListener> eventListener)480 void SVGElementInstance::setOndrag(PassRefPtr<EventListener> eventListener)
481 {
482     correspondingElement()->setAttributeEventListener(eventNames().dragEvent, eventListener);
483 }
484 
ondragend() const485 EventListener* SVGElementInstance::ondragend() const
486 {
487     return correspondingElement()->getAttributeEventListener(eventNames().dragendEvent);
488 }
489 
setOndragend(PassRefPtr<EventListener> eventListener)490 void SVGElementInstance::setOndragend(PassRefPtr<EventListener> eventListener)
491 {
492     correspondingElement()->setAttributeEventListener(eventNames().dragendEvent, eventListener);
493 }
494 
onreset() const495 EventListener* SVGElementInstance::onreset() const
496 {
497     return correspondingElement()->getAttributeEventListener(eventNames().resetEvent);
498 }
499 
setOnreset(PassRefPtr<EventListener> eventListener)500 void SVGElementInstance::setOnreset(PassRefPtr<EventListener> eventListener)
501 {
502     correspondingElement()->setAttributeEventListener(eventNames().resetEvent, eventListener);
503 }
504 
onresize() const505 EventListener* SVGElementInstance::onresize() const
506 {
507     return correspondingElement()->getAttributeEventListener(eventNames().resizeEvent);
508 }
509 
setOnresize(PassRefPtr<EventListener> eventListener)510 void SVGElementInstance::setOnresize(PassRefPtr<EventListener> eventListener)
511 {
512     correspondingElement()->setAttributeEventListener(eventNames().resizeEvent, eventListener);
513 }
514 
onscroll() const515 EventListener* SVGElementInstance::onscroll() const
516 {
517     return correspondingElement()->getAttributeEventListener(eventNames().scrollEvent);
518 }
519 
setOnscroll(PassRefPtr<EventListener> eventListener)520 void SVGElementInstance::setOnscroll(PassRefPtr<EventListener> eventListener)
521 {
522     correspondingElement()->setAttributeEventListener(eventNames().scrollEvent, eventListener);
523 }
524 
onsearch() const525 EventListener* SVGElementInstance::onsearch() const
526 {
527     return correspondingElement()->getAttributeEventListener(eventNames().searchEvent);
528 }
529 
setOnsearch(PassRefPtr<EventListener> eventListener)530 void SVGElementInstance::setOnsearch(PassRefPtr<EventListener> eventListener)
531 {
532     correspondingElement()->setAttributeEventListener(eventNames().searchEvent, eventListener);
533 }
534 
onselect() const535 EventListener* SVGElementInstance::onselect() const
536 {
537     return correspondingElement()->getAttributeEventListener(eventNames().selectEvent);
538 }
539 
setOnselect(PassRefPtr<EventListener> eventListener)540 void SVGElementInstance::setOnselect(PassRefPtr<EventListener> eventListener)
541 {
542     correspondingElement()->setAttributeEventListener(eventNames().selectEvent, eventListener);
543 }
544 
onselectstart() const545 EventListener* SVGElementInstance::onselectstart() const
546 {
547     return correspondingElement()->getAttributeEventListener(eventNames().selectstartEvent);
548 }
549 
setOnselectstart(PassRefPtr<EventListener> eventListener)550 void SVGElementInstance::setOnselectstart(PassRefPtr<EventListener> eventListener)
551 {
552     correspondingElement()->setAttributeEventListener(eventNames().selectstartEvent, eventListener);
553 }
554 
onsubmit() const555 EventListener* SVGElementInstance::onsubmit() const
556 {
557     return correspondingElement()->getAttributeEventListener(eventNames().submitEvent);
558 }
559 
setOnsubmit(PassRefPtr<EventListener> eventListener)560 void SVGElementInstance::setOnsubmit(PassRefPtr<EventListener> eventListener)
561 {
562     correspondingElement()->setAttributeEventListener(eventNames().submitEvent, eventListener);
563 }
564 
onunload() const565 EventListener* SVGElementInstance::onunload() const
566 {
567     return correspondingElement()->getAttributeEventListener(eventNames().unloadEvent);
568 }
569 
setOnunload(PassRefPtr<EventListener> eventListener)570 void SVGElementInstance::setOnunload(PassRefPtr<EventListener> eventListener)
571 {
572     correspondingElement()->setAttributeEventListener(eventNames().unloadEvent, eventListener);
573 }
574 
575 }
576 
577 #endif // ENABLE(SVG)
578