Diff
Modified: branches/chromium/1084/LayoutTests/ChangeLog (113392 => 113393)
--- branches/chromium/1084/LayoutTests/ChangeLog 2012-04-05 23:20:31 UTC (rev 113392)
+++ branches/chromium/1084/LayoutTests/ChangeLog 2012-04-05 23:28:21 UTC (rev 113393)
@@ -12,6 +12,18 @@
* webintents/web-intents-api.html:
* webintents/web-intents-invoke.html:
+2012-04-03 Erik Arvidsson <[email protected]>
+
+ [v8] Fix memory leak in V8LazyEventListener
+ https://bugs.webkit.org/show_bug.cgi?id=83057
+
+ Reviewed by Ojan Vafai.
+
+ * fast/dom/inline-event-attributes-moved-expected.txt: Added.
+ * fast/dom/inline-event-attributes-moved.html: Added.
+ * fast/dom/inline-event-attributes-release-expected.txt: Added.
+ * fast/dom/inline-event-attributes-release.html: Added.
+
2012-03-27 Dirk Pranke <[email protected]>
Remove a bunch of lines that are no longer failing.
Copied: branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-moved-expected.txt (from rev 113086, trunk/LayoutTests/fast/dom/inline-event-attributes-moved-expected.txt) (0 => 113393)
--- branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-moved-expected.txt (rev 0)
+++ branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-moved-expected.txt 2012-04-05 23:28:21 UTC (rev 113393)
@@ -0,0 +1,10 @@
+Tests that we have the expected form in scope
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS expected is "undefined"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Copied: branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-moved.html (from rev 113086, trunk/LayoutTests/fast/dom/inline-event-attributes-moved.html) (0 => 113393)
--- branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-moved.html (rev 0)
+++ branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-moved.html 2012-04-05 23:28:21 UTC (rev 113393)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+
+description('Tests that we have the expected form in scope');
+
+function dispatchClick(element)
+{
+ var clickEvent = document.createEvent('MouseEvent');
+ clickEvent.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ element.dispatchEvent(clickEvent);
+}
+
+var expected;
+var f = document.createElement('form');
+var i = f.appendChild(document.createElement('input'));
+i.setAttribute('onclick', 'expected = typeof action');
+f.removeChild(i);
+f = null;
+gc();
+dispatchClick(i);
+shouldBeEqualToString('expected', 'undefined');
+
+</script>
+<script src=""
\ No newline at end of file
Copied: branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-release-expected.txt (from rev 113086, trunk/LayoutTests/fast/dom/inline-event-attributes-release-expected.txt) (0 => 113393)
--- branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-release-expected.txt (rev 0)
+++ branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-release-expected.txt 2012-04-05 23:28:21 UTC (rev 113393)
@@ -0,0 +1,10 @@
+Tests that we do not hold on to any nodes
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS afterCount - beforeCount is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Copied: branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-release.html (from rev 113086, trunk/LayoutTests/fast/dom/inline-event-attributes-release.html) (0 => 113393)
--- branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-release.html (rev 0)
+++ branches/chromium/1084/LayoutTests/fast/dom/inline-event-attributes-release.html 2012-04-05 23:28:21 UTC (rev 113393)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+
+description('Tests that we do not hold on to any nodes');
+
+gc();
+
+function numberOfLiveNodes() {
+ return window.internals && window.internals.numberOfLiveNodes && window.internals.numberOfLiveNodes();
+}
+
+var beforeCount = numberOfLiveNodes();
+
+var f = document.createElement('form');
+var i = f.appendChild(document.createElement('input'));
+i.setAttribute('onclick', '');
+f.removeChild(i);
+f = null;
+i = null;
+gc();
+
+var afterCount = numberOfLiveNodes();
+
+shouldBe('afterCount - beforeCount', '0');
+
+</script>
+<script src=""
\ No newline at end of file
Modified: branches/chromium/1084/Source/WebCore/bindings/v8/V8LazyEventListener.cpp (113392 => 113393)
--- branches/chromium/1084/Source/WebCore/bindings/v8/V8LazyEventListener.cpp 2012-04-05 23:20:31 UTC (rev 113392)
+++ branches/chromium/1084/Source/WebCore/bindings/v8/V8LazyEventListener.cpp 2012-04-05 23:28:21 UTC (rev 113393)
@@ -50,18 +50,15 @@
namespace WebCore {
-V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition& position, PassRefPtr<Node> node, const WorldContextHandle& worldContext)
+V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition& position, Node* node, const WorldContextHandle& worldContext)
: V8AbstractEventListener(true, worldContext)
, m_functionName(functionName)
, m_eventParameterName(eventParameterName)
, m_code(code)
, m_sourceURL(sourceURL)
, m_node(node)
- , m_formElement(0)
, m_position(position)
{
- if (m_node && m_node->isHTMLElement())
- m_formElement = static_cast<HTMLElement*>(m_node.get())->form();
}
template<typename T>
@@ -165,13 +162,14 @@
ASSERT(value->IsFunction());
v8::Local<v8::Function> intermediateFunction = value.As<v8::Function>();
- v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node.get());
- v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(m_formElement.get());
+ HTMLFormElement* formElement = 0;
+ if (m_node && m_node->isHTMLElement())
+ formElement = static_cast<HTMLElement*>(m_node)->form();
+
+ v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node);
+ v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement);
v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0);
- m_node.clear();
- m_formElement.clear();
-
v8::Handle<v8::Value> parameters[3] = { nodeWrapper, formWrapper, documentWrapper };
// Use Call directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext().
@@ -212,6 +210,12 @@
wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));
+ // Since we only parse once, there's no need to keep data used for parsing around anymore.
+ m_functionName = String();
+ m_code = String();
+ m_eventParameterName = String();
+ m_sourceURL = String();
+
setListenerObject(wrappedFunction);
}
Modified: branches/chromium/1084/Source/WebCore/bindings/v8/V8LazyEventListener.h (113392 => 113393)
--- branches/chromium/1084/Source/WebCore/bindings/v8/V8LazyEventListener.h 2012-04-05 23:20:31 UTC (rev 113392)
+++ branches/chromium/1084/Source/WebCore/bindings/v8/V8LazyEventListener.h 2012-04-05 23:28:21 UTC (rev 113393)
@@ -48,7 +48,7 @@
// A V8LazyEventListener is either a HTML or SVG event handler.
class V8LazyEventListener : public V8AbstractEventListener {
public:
- static PassRefPtr<V8LazyEventListener> create(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String& sourceURL, const TextPosition& position, PassRefPtr<Node> node, const WorldContextHandle& worldContext)
+ static PassRefPtr<V8LazyEventListener> create(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String& sourceURL, const TextPosition& position, Node* node, const WorldContextHandle& worldContext)
{
return adoptRef(new V8LazyEventListener(functionName, eventParameterName, code, sourceURL, position, node, worldContext));
}
@@ -59,7 +59,7 @@
virtual void prepareListenerObject(ScriptExecutionContext*);
private:
- V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition&, PassRefPtr<Node>, const WorldContextHandle&);
+ V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition&, Node*, const WorldContextHandle&);
virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*);
@@ -73,8 +73,7 @@
AtomicString m_eventParameterName;
String m_code;
String m_sourceURL;
- RefPtr<Node> m_node;
- RefPtr<HTMLFormElement> m_formElement;
+ Node* m_node;
TextPosition m_position;
};