Commit ec7365b9 authored by ap@webkit.org's avatar ap@webkit.org

Reviewed by Darin Adler.

        https://bugs.webkit.org/show_bug.cgi?id=22001
        AtomicStringImpl* keys of event listener maps can outlive their strings

        Test: fast/events/destroyed-atomic-string.html

        * dom/MessagePort.cpp:
        (WebCore::MessagePort::addEventListener):
        (WebCore::MessagePort::removeEventListener):
        (WebCore::MessagePort::dispatchEvent):
        * dom/MessagePort.h:
        * loader/appcache/DOMApplicationCache.cpp:
        (WebCore::DOMApplicationCache::addEventListener):
        (WebCore::DOMApplicationCache::removeEventListener):
        (WebCore::DOMApplicationCache::dispatchEvent):
        * loader/appcache/DOMApplicationCache.h:
        * xml/XMLHttpRequest.cpp:
        (WebCore::XMLHttpRequest::addEventListener):
        (WebCore::XMLHttpRequest::removeEventListener):
        (WebCore::XMLHttpRequest::dispatchEvent):
        * xml/XMLHttpRequest.h:
        * xml/XMLHttpRequestUpload.cpp:
        (WebCore::XMLHttpRequestUpload::addEventListener):
        (WebCore::XMLHttpRequestUpload::removeEventListener):
        (WebCore::XMLHttpRequestUpload::dispatchEvent):
        * xml/XMLHttpRequestUpload.h:
        Changed EventListenersMap to use AtomicString as key (instead of AtomicStringImpl*).



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@38064 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f319b265
2008-11-01 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin Adler.
https://bugs.webkit.org/show_bug.cgi?id=22001
AtomicStringImpl* keys of event listener maps can outlive their strings
* fast/events/destroyed-atomic-string-expected.txt: Added.
* fast/events/destroyed-atomic-string.html: Added.
2008-10-30 Justin Garcia <justin.garcia@apple.com>
Added another layout test for previous check-in.
......
Test that adding an event listener for an event with a unique name works correctly (this used to corrupt event listener map after GC).
PASS
<body>
<p>Test that adding an event listener for an event with a unique name works correctly (this used to corrupt event listener map after GC).</p>
<pre id=log></pre>
<script>
function gc()
{
if (window.GCController)
return GCController.collect();
for (var i = 0; i < 10000; i++) { // > force garbage collection (FF requires about 9K allocations before a collect)
var s = new String("abc");
}
}
function log(message)
{
document.getElementById("log").innerHTML += message + "<br>";
}
if (window.layoutTestController)
layoutTestController.dumpAsText();
var listenerCallCount = 0;
var expectedListenerCallCount = 0;
function listener()
{
++listenerCallCount;
}
function addListener(targetName, name)
{
var target;
try {
target = eval(targetName);
eval(target).addEventListener(name, listener, true);
++expectedListenerCallCount;
} catch (ex) {
log((target ? target : targetName) + " is not supported, or cannot be used to register arbitrary event handlers.");
}
}
function dispatchEvent(target, name)
{
try {
var evt = document.createEvent("MessageEvent");
evt.initMessageEvent(name);
eval(target).dispatchEvent(evt);
} catch (ex) {
}
}
var xhr = new XMLHttpRequest;
addListener("xhr", "foo1");
addListener("xhr.upload", "foo2");
addListener("window.applicationCache", "foo3");
var channel;
try {
channel = new MessageChannel;
channel.port1.addEventListener("foo4", listener, true);
++expectedListenerCallCount;
} catch (ex) {
log("MessageChannel is not supported, or cannot be used to register arbitrary event handlers.");
}
// window.dispatchEvent is currently unimplemented.
// window.addEventListener("foo5", listener, true);
// ++expectedListenerCallCount;
document.body.addEventListener("foo6", listener, true);
++expectedListenerCallCount;
gc();
dispatchEvent("xhr", "foo1");
dispatchEvent("xhr.upload", "foo2");
dispatchEvent("window.applicationCache", "foo3");
dispatchEvent("channel.port1", "foo4");
dispatchEvent("window", "foo5");
dispatchEvent("document.body", "foo6");
gc();
log((listenerCallCount == expectedListenerCallCount) ? "PASS" : "FAIL");
</script>
</body>
2008-11-01 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin Adler.
https://bugs.webkit.org/show_bug.cgi?id=22001
AtomicStringImpl* keys of event listener maps can outlive their strings
Test: fast/events/destroyed-atomic-string.html
* dom/MessagePort.cpp:
(WebCore::MessagePort::addEventListener):
(WebCore::MessagePort::removeEventListener):
(WebCore::MessagePort::dispatchEvent):
* dom/MessagePort.h:
* loader/appcache/DOMApplicationCache.cpp:
(WebCore::DOMApplicationCache::addEventListener):
(WebCore::DOMApplicationCache::removeEventListener):
(WebCore::DOMApplicationCache::dispatchEvent):
* loader/appcache/DOMApplicationCache.h:
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::addEventListener):
(WebCore::XMLHttpRequest::removeEventListener):
(WebCore::XMLHttpRequest::dispatchEvent):
* xml/XMLHttpRequest.h:
* xml/XMLHttpRequestUpload.cpp:
(WebCore::XMLHttpRequestUpload::addEventListener):
(WebCore::XMLHttpRequestUpload::removeEventListener):
(WebCore::XMLHttpRequestUpload::dispatchEvent):
* xml/XMLHttpRequestUpload.h:
Changed EventListenersMap to use AtomicString as key (instead of AtomicStringImpl*).
2008-10-31 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin Adler.
......
......@@ -252,11 +252,11 @@ void MessagePort::dispatchCloseEvent()
void MessagePort::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end()) {
ListenerVector listeners;
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
} else {
ListenerVector& listeners = iter->second;
for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
......@@ -265,13 +265,13 @@ void MessagePort::addEventListener(const AtomicString& eventType, PassRefPtr<Eve
}
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
}
}
void MessagePort::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool useCapture)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end())
return;
......@@ -291,7 +291,7 @@ bool MessagePort::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
return true;
}
ListenerVector listenersCopy = m_eventListeners.get(event->type().impl());
ListenerVector listenersCopy = m_eventListeners.get(event->type());
for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
event->setTarget(this);
event->setCurrentTarget(this);
......
......@@ -27,6 +27,7 @@
#ifndef MessagePort_h
#define MessagePort_h
#include "AtomicStringHash.h"
#include "EventListener.h"
#include "EventTarget.h"
......@@ -79,7 +80,7 @@ namespace WebCore {
virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
typedef Vector<RefPtr<EventListener> > ListenerVector;
typedef HashMap<AtomicStringImpl*, ListenerVector> EventListenersMap;
typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
EventListenersMap& eventListeners() { return m_eventListeners; }
using ThreadSafeShared<MessagePort>::ref;
......
......@@ -183,11 +183,11 @@ ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const
void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end()) {
ListenerVector listeners;
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
} else {
ListenerVector& listeners = iter->second;
for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
......@@ -196,13 +196,13 @@ void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRe
}
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
}
}
void DOMApplicationCache::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool useCapture)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end())
return;
......@@ -222,7 +222,7 @@ bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode&
return true;
}
ListenerVector listenersCopy = m_eventListeners.get(event->type().impl());
ListenerVector listenersCopy = m_eventListeners.get(event->type());
for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
event->setTarget(this);
event->setCurrentTarget(this);
......
......@@ -28,12 +28,12 @@
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include <wtf/RefCounted.h>
#include "AtomicStringHash.h"
#include "EventTarget.h"
#include "EventListener.h"
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
namespace WebCore {
......@@ -72,7 +72,7 @@ public:
virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
typedef Vector<RefPtr<EventListener> > ListenerVector;
typedef HashMap<AtomicStringImpl*, ListenerVector> EventListenersMap;
typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
EventListenersMap& eventListeners() { return m_eventListeners; }
using RefCounted<DOMApplicationCache>::ref;
......
......@@ -241,11 +241,11 @@ XMLHttpRequestUpload* XMLHttpRequest::upload()
void XMLHttpRequest::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end()) {
ListenerVector listeners;
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
} else {
ListenerVector& listeners = iter->second;
for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
......@@ -253,13 +253,13 @@ void XMLHttpRequest::addEventListener(const AtomicString& eventType, PassRefPtr<
return;
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
}
}
void XMLHttpRequest::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end())
return;
......@@ -279,7 +279,7 @@ bool XMLHttpRequest::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& ec)
return true;
}
ListenerVector listenersCopy = m_eventListeners.get(evt->type().impl());
ListenerVector listenersCopy = m_eventListeners.get(evt->type());
for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
evt->setTarget(this);
evt->setCurrentTarget(this);
......
......@@ -21,6 +21,7 @@
#define XMLHttpRequest_h
#include "ActiveDOMObject.h"
#include "AtomicStringHash.h"
#include "EventListener.h"
#include "EventTarget.h"
#include "FormData.h"
......@@ -97,7 +98,7 @@ public:
EventListener* onprogress() const { return m_onProgressListener.get(); }
typedef Vector<RefPtr<EventListener> > ListenerVector;
typedef HashMap<AtomicStringImpl*, ListenerVector> EventListenersMap;
typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
// useCapture is not used, even for add/remove pairing (for Firefox compatibility).
virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
......
......@@ -54,11 +54,11 @@ ScriptExecutionContext* XMLHttpRequestUpload::scriptExecutionContext() const
void XMLHttpRequestUpload::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end()) {
ListenerVector listeners;
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
} else {
ListenerVector& listeners = iter->second;
for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
......@@ -67,13 +67,13 @@ void XMLHttpRequestUpload::addEventListener(const AtomicString& eventType, PassR
}
listeners.append(eventListener);
m_eventListeners.add(eventType.impl(), listeners);
m_eventListeners.add(eventType, listeners);
}
}
void XMLHttpRequestUpload::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
{
EventListenersMap::iterator iter = m_eventListeners.find(eventType.impl());
EventListenersMap::iterator iter = m_eventListeners.find(eventType);
if (iter == m_eventListeners.end())
return;
......@@ -94,7 +94,7 @@ bool XMLHttpRequestUpload::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& e
return true;
}
ListenerVector listenersCopy = m_eventListeners.get(evt->type().impl());
ListenerVector listenersCopy = m_eventListeners.get(evt->type());
for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
evt->setTarget(this);
evt->setCurrentTarget(this);
......
......@@ -26,6 +26,7 @@
#ifndef XMLHttpRequestUpload_h
#define XMLHttpRequestUpload_h
#include "AtomicStringHash.h"
#include "EventListener.h"
#include "EventTarget.h"
#include <wtf/HashMap.h>
......@@ -76,7 +77,7 @@ namespace WebCore {
EventListener* onprogress() const { return m_onProgressListener.get(); }
typedef Vector<RefPtr<EventListener> > ListenerVector;
typedef HashMap<AtomicStringImpl*, ListenerVector> EventListenersMap;
typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment