- 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