Title: [108082] trunk
Revision
108082
Author
[email protected]
Date
2012-02-17 08:50:13 -0800 (Fri, 17 Feb 2012)

Log Message

chrome.dll!WebCore::SVGTRefElement::updateReferencedText ReadAV@NULL (e85cb8e140071fa7790cad215b0109dc)
https://bugs.webkit.org/show_bug.cgi?id=74858

Patch by Florin Malita <[email protected]> on 2012-02-17
Reviewed by Nikolas Zimmermann.

Source/WebCore:

Tests: svg/custom/tref-remove-target-crash-expected.svg
       svg/custom/tref-remove-target-crash.svg

Add a DOMNodeRemovedFromDocumentEvent listener to detect when the target element is removed. Upon removal,
cleanup all listeners and re-activate the pending resource to attach if the referenced ID is added
at a later time programmatically. Also move the DOMSubtreeModifiedEvent listener from the parent to
the target element to simplify the implementation and reduce the scope.

* svg/SVGTRefElement.cpp:
(WebCore::TargetListener::create):
(WebCore::TargetListener::cast):
(WebCore::TargetListener::clear):
(WebCore::TargetListener::TargetListener):
(WebCore::TargetListener::operator==):
(WebCore::TargetListener::handleEvent):
(WebCore::SVGTRefElement::detachTarget):
(WebCore::SVGTRefElement::buildPendingResource):
* svg/SVGTRefElement.h:

LayoutTests:

* svg/custom/tref-remove-target-crash-expected.svg: Added.
* svg/custom/tref-remove-target-crash.svg: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (108081 => 108082)


--- trunk/LayoutTests/ChangeLog	2012-02-17 16:48:09 UTC (rev 108081)
+++ trunk/LayoutTests/ChangeLog	2012-02-17 16:50:13 UTC (rev 108082)
@@ -1,3 +1,13 @@
+2012-02-17  Florin Malita  <[email protected]>
+
+        chrome.dll!WebCore::SVGTRefElement::updateReferencedText ReadAV@NULL (e85cb8e140071fa7790cad215b0109dc)
+        https://bugs.webkit.org/show_bug.cgi?id=74858
+
+        Reviewed by Nikolas Zimmermann.
+
+        * svg/custom/tref-remove-target-crash-expected.svg: Added.
+        * svg/custom/tref-remove-target-crash.svg: Added.
+
 2012-02-17  Pavel Feldman  <[email protected]>
 
         Web Inspector: check undo-redo boundaries based on current action index, not history size.

Added: trunk/LayoutTests/svg/custom/tref-remove-target-crash-expected.svg (0 => 108082)


--- trunk/LayoutTests/svg/custom/tref-remove-target-crash-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/custom/tref-remove-target-crash-expected.svg	2012-02-17 16:50:13 UTC (rev 108082)
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <text x="200" y="50" font-family="Verdana" font-size="25" fill="green">QUX</text>
+</svg>

Added: trunk/LayoutTests/svg/custom/tref-remove-target-crash.svg (0 => 108082)


--- trunk/LayoutTests/svg/custom/tref-remove-target-crash.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/custom/tref-remove-target-crash.svg	2012-02-17 16:50:13 UTC (rev 108082)
@@ -0,0 +1,26 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <text x="100" y="50" font-family="Verdana" font-size="25" fill="green">
+    <!-- Removing the referenced text element should not cause a crash -->
+    <tref xlink:href=""
+  </text>
+  <text x="200" y="50" font-family="Verdana" font-size="25" fill="green">
+    <!-- This should pick up the replaced text element and its updated text content -->
+    <tref xlink:href=""
+  </text>
+
+  <text x="100" y="100" id="text1">FOO</text>
+  <text x="200" y="100" id="text2">BAR</text>
+
+<script>
+  var el1 = document.getElementById('text1');
+  el1.parentNode.removeChild(el1);
+  var el2 = document.getElementById('text2');
+  el2.parentNode.removeChild(el2);
+  var newel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
+  newel.setAttribute('id', 'text2');
+  newel.setAttribute('visibility', 'hidden');
+  newel.textContent = 'BAZ';
+  document.documentElement.appendChild(newel);
+  document.getElementById('text2').textContent = 'QUX';
+</script>
+</svg>

Modified: trunk/Source/WebCore/ChangeLog (108081 => 108082)


--- trunk/Source/WebCore/ChangeLog	2012-02-17 16:48:09 UTC (rev 108081)
+++ trunk/Source/WebCore/ChangeLog	2012-02-17 16:50:13 UTC (rev 108082)
@@ -1,3 +1,29 @@
+2012-02-17  Florin Malita  <[email protected]>
+
+        chrome.dll!WebCore::SVGTRefElement::updateReferencedText ReadAV@NULL (e85cb8e140071fa7790cad215b0109dc)
+        https://bugs.webkit.org/show_bug.cgi?id=74858
+
+        Reviewed by Nikolas Zimmermann.
+
+        Tests: svg/custom/tref-remove-target-crash-expected.svg
+               svg/custom/tref-remove-target-crash.svg
+
+        Add a DOMNodeRemovedFromDocumentEvent listener to detect when the target element is removed. Upon removal,
+        cleanup all listeners and re-activate the pending resource to attach if the referenced ID is added
+        at a later time programmatically. Also move the DOMSubtreeModifiedEvent listener from the parent to
+        the target element to simplify the implementation and reduce the scope.
+
+        * svg/SVGTRefElement.cpp:
+        (WebCore::TargetListener::create):
+        (WebCore::TargetListener::cast):
+        (WebCore::TargetListener::clear):
+        (WebCore::TargetListener::TargetListener):
+        (WebCore::TargetListener::operator==):
+        (WebCore::TargetListener::handleEvent):
+        (WebCore::SVGTRefElement::detachTarget):
+        (WebCore::SVGTRefElement::buildPendingResource):
+        * svg/SVGTRefElement.h:
+
 2012-02-17  Simon Fraser  <[email protected]>
 
         Fix the build after r108077.

Modified: trunk/Source/WebCore/svg/SVGTRefElement.cpp (108081 => 108082)


--- trunk/Source/WebCore/svg/SVGTRefElement.cpp	2012-02-17 16:48:09 UTC (rev 108081)
+++ trunk/Source/WebCore/svg/SVGTRefElement.cpp	2012-02-17 16:50:13 UTC (rev 108082)
@@ -62,16 +62,16 @@
     return element.release();
 }
 
-class SubtreeModificationEventListener : public EventListener {
+class TargetListener : public EventListener {
 public:
-    static PassRefPtr<SubtreeModificationEventListener> create(SVGTRefElement* trefElement, String targetId)
+    static PassRefPtr<TargetListener> create(SVGTRefElement* trefElement, String targetId)
     {
-        return adoptRef(new SubtreeModificationEventListener(trefElement, targetId));
+        return adoptRef(new TargetListener(trefElement, targetId));
     }
 
-    static const SubtreeModificationEventListener* cast(const EventListener* listener)
+    static const TargetListener* cast(const EventListener* listener)
     {
-        return listener->type() == CPPEventListenerType ? static_cast<const SubtreeModificationEventListener*>(listener) : 0;
+        return listener->type() == CPPEventListenerType ? static_cast<const TargetListener*>(listener) : 0;
     }
 
     virtual bool operator==(const EventListener&);
@@ -79,15 +79,17 @@
     void clear()
     {
         Element* target = m_trefElement->treeScope()->getElementById(m_targetId);
-        if (target && target->parentNode())
-            target->parentNode()->removeEventListener(eventNames().DOMSubtreeModifiedEvent, this, false);
+        if (target) {
+            target->removeEventListener(eventNames().DOMSubtreeModifiedEvent, this, false);
+            target->removeEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, false);
+        }
         
         m_trefElement = 0;
         m_targetId = String();
     }
 
 private:
-    SubtreeModificationEventListener(SVGTRefElement* trefElement, String targetId)
+    TargetListener(SVGTRefElement* trefElement, String targetId)
         : EventListener(CPPEventListenerType)
         , m_trefElement(trefElement)
         , m_targetId(targetId)
@@ -100,17 +102,20 @@
     String m_targetId;
 };
 
-bool SubtreeModificationEventListener::operator==(const EventListener& listener)
+bool TargetListener::operator==(const EventListener& listener)
 {
-    if (const SubtreeModificationEventListener* subtreeModificationEventListener = SubtreeModificationEventListener::cast(&listener))
+    if (const TargetListener* subtreeModificationEventListener = TargetListener::cast(&listener))
         return m_trefElement == subtreeModificationEventListener->m_trefElement;
     return false;
 }
 
-void SubtreeModificationEventListener::handleEvent(ScriptExecutionContext*, Event* event)
+void TargetListener::handleEvent(ScriptExecutionContext*, Event* event)
 {
     if (m_trefElement && event->type() == eventNames().DOMSubtreeModifiedEvent && m_trefElement != event->target())
         m_trefElement->updateReferencedText();
+
+    if (m_trefElement && event->type() == eventNames().DOMNodeRemovedFromDocumentEvent)
+        m_trefElement->detachTarget();
 }
 
 class SVGShadowText : public Text {
@@ -168,6 +173,26 @@
         root->firstChild()->setTextContent(textContent, ASSERT_NO_EXCEPTION);
 }
 
+void SVGTRefElement::detachTarget()
+{
+    // Remove active listeners and clear the text content.
+    clearEventListener();
+
+    String emptyContent;
+    ExceptionCode ignore = 0;
+
+    ASSERT(hasShadowRoot());
+    Node* container = shadowRootList()->oldestShadowRoot()->firstChild();
+    if (container)
+        container->setTextContent(emptyContent, ignore);
+
+    // Mark the referenced ID as pending.
+    String id;
+    SVGURIReference::targetElementFromIRIString(href(), document(), &id);
+    if (!hasPendingResources() && !id.isEmpty())
+        document()->accessSVGExtensions()->addPendingResource(id, this);
+}
+
 bool SVGTRefElement::isSupportedAttribute(const QualifiedName& attrName)
 {
     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
@@ -257,9 +282,9 @@
     if (!inDocument())
         return;
 
-    m_eventListener = SubtreeModificationEventListener::create(this, id);
-    ASSERT(target->parentNode());
-    target->parentNode()->addEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false);
+    m_eventListener = TargetListener::create(this, id);
+    target->addEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false);
+    target->addEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, m_eventListener.get(), false);
 }
 
 void SVGTRefElement::insertedIntoDocument()

Modified: trunk/Source/WebCore/svg/SVGTRefElement.h (108081 => 108082)


--- trunk/Source/WebCore/svg/SVGTRefElement.h	2012-02-17 16:48:09 UTC (rev 108081)
+++ trunk/Source/WebCore/svg/SVGTRefElement.h	2012-02-17 16:50:13 UTC (rev 108082)
@@ -27,7 +27,7 @@
 
 namespace WebCore {
 
-class SubtreeModificationEventListener;
+class TargetListener;
 
 class SVGTRefElement : public SVGTextPositioningElement,
                        public SVGURIReference {
@@ -35,7 +35,7 @@
     static PassRefPtr<SVGTRefElement> create(const QualifiedName&, Document*);
 
 private:
-    friend class SubtreeModificationEventListener;
+    friend class TargetListener;
 
     SVGTRefElement(const QualifiedName&, Document*);
     virtual ~SVGTRefElement();
@@ -57,13 +57,15 @@
 
     void updateReferencedText();
 
+    void detachTarget();
+
     virtual void buildPendingResource();
 
     BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGTRefElement)
         DECLARE_ANIMATED_STRING(Href, href)
     END_DECLARE_ANIMATED_PROPERTIES
 
-    RefPtr<SubtreeModificationEventListener> m_eventListener;
+    RefPtr<TargetListener> m_eventListener;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to