Reviewed by Darin.
- fixed <rdar://problem/4125222> Dashboard heap size grows over time (leak caused by JavaScript DOM node wrappers?)
- changed per-document DOMObject caching to work with DOMNodes, since that is all it was used for anyway.
Test cases added: (these tests actually ensure that DOM wrappers
are sufficiently protected from GC to match other browsers, they
do not verify that the leak is fixed since there's no way to test
that with layout tests).
* layout-tests/fast/dom/gc-1-expected.txt: Added.
* layout-tests/fast/dom/gc-1.html: Added.
* layout-tests/fast/dom/gc-2-expected.txt: Added.
* layout-tests/fast/dom/gc-2.html: Added.
* layout-tests/fast/dom/gc-3-expected.txt: Added.
* layout-tests/fast/dom/gc-3.html: Added.
* khtml/ecma/kjs_binding.cpp:
(KJS::ScriptInterpreter::forgetDOMObjectForDocument): New function - allows nodes
that get removed from the document to go away from the cache if not referenced.
(KJS::ScriptInterpreter::mark): Don't mark nodes that aren't in the document,
they can stay in the cache but only if they have another source of life.
(KJS::ScriptInterpreter::domNodesPerDocument): Renamed and changed parameter types.
(KJS::ScriptInterpreter::getDOMNodeForDocument): Renamed and changed parameter types.
(KJS::ScriptInterpreter::forgetDOMNodeForDocument): Renamed and changed parameter types.
(KJS::ScriptInterpreter::putDOMNodeForDocument): Renamed and changed parameter types.
(KJS::ScriptInterpreter::forgetAllDOMNodesForDocument): Renamed and changed parameter types.
(KJS::ScriptInterpreter::updateDOMNodeDocument): Renamed and changed parameter types.
* khtml/ecma/kjs_binding.h:
* khtml/ecma/kjs_dom.cpp:
(KJS::DOMNode::~DOMNode): call forgetDOMObjectForDocument.
(KJS::DOMNode::mark): If the node is not in the document, make sure to mark
all wrappers in its detached piece of the tree.
(KJS::getDOMNode): Updated for renames
* khtml/ecma/kjs_dom.h:
* khtml/xml/dom_docimpl.cpp:
(DocumentImpl::~DocumentImpl): Updated for renames.
* khtml/xml/dom_nodeimpl.cpp:
(NodeImpl::checkAddChild): Updated for renames.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@9230 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/fast/dom/gc-1-expected.txt b/LayoutTests/fast/dom/gc-1-expected.txt
new file mode 100644
index 0000000..fde5891
--- /dev/null
+++ b/LayoutTests/fast/dom/gc-1-expected.txt
@@ -0,0 +1,7 @@
+This test verifies that JavaScript wrappers for DOM nodes are protected against garbage collection as long as the node remains in the document (so custom properties are preserved).
+
+The output should be the following pieces of text on lines by themselves: "original span", "B":
+
+original span
+B
+
diff --git a/LayoutTests/fast/dom/gc-1.html b/LayoutTests/fast/dom/gc-1.html
new file mode 100644
index 0000000..1a055e5
--- /dev/null
+++ b/LayoutTests/fast/dom/gc-1.html
@@ -0,0 +1,41 @@
+<head>
+<script>
+function doit()
+{
+ document.getElementById("span-B").customProperty = "B";
+
+ // create lots of objects to force a garbage collection
+ var i = 0;
+ while (i < 1000) {
+ i = i+1;
+ }
+
+ var output= document.getElementById("output");
+
+ output.innerHTML += document.getElementById("span-B").customProperty + "<BR>";
+}
+
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+}
+
+</script>
+</head>
+
+<body onload="doit()">
+<div style="border: 1px solid red">
+<p>
+This test verifies that JavaScript wrappers for DOM nodes are
+protected against garbage collection as long as the node remains in
+the document (so custom properties are preserved).
+</p>
+<p>
+The output should be the following pieces of text on lines by themselves: "original span", "B":
+</p>
+</div>
+<div id="div">
+<span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span>
+</div>
+<div id="output">
+</div>
+</body>
diff --git a/LayoutTests/fast/dom/gc-2-expected.txt b/LayoutTests/fast/dom/gc-2-expected.txt
new file mode 100644
index 0000000..3c76ffe
--- /dev/null
+++ b/LayoutTests/fast/dom/gc-2-expected.txt
@@ -0,0 +1,9 @@
+This test verifies that JavaScript wrappers for DOM nodes are protected against garbage collection for node trees that are outside the document, so long as there's a reference to at least one node in the tree.
+
+The output should be the following pieces of text on lines by themselves: "replacement content", "B", "A", "C".
+
+replacement content
+B
+A
+C
+
diff --git a/LayoutTests/fast/dom/gc-2.html b/LayoutTests/fast/dom/gc-2.html
new file mode 100644
index 0000000..4e8fe25
--- /dev/null
+++ b/LayoutTests/fast/dom/gc-2.html
@@ -0,0 +1,55 @@
+<html>
+<head>
+<script>
+function doit()
+{
+ var B = document.getElementById("span-B");
+ B.customProperty = "B";
+ B.parentNode.customProperty = "A";
+ B.firstChild.customProperty = "C";
+
+ document.getElementById("div").innerHTML = "<span>replacement content</span>";
+
+ // create lots of objects to force a garbage collection
+ var i = "";
+ while (i < 1000) {
+ i = i + "a";
+ }
+
+ var output= document.getElementById("output");
+
+ output.innerHTML += B.customProperty + "<BR>";
+ if (B.parentNode) {
+ output.innerHTML += B.parentNode.customProperty + "<BR>";
+ }
+ if (B.firstChild) {
+ output.innerHTML += B.firstChild.customProperty + "<BR>";
+ }
+}
+
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+}
+
+</script>
+</head>
+
+<body onload="doit()">
+<div style="border: 1px solid red">
+<p>
+This test verifies that JavaScript wrappers for DOM nodes are
+protected against garbage collection for node trees that are outside
+the document, so long as there's a reference to at least one node in
+the tree.
+</p>
+<p>
+The output should be the following pieces of text on lines by themselves: "replacement content", "B", "A", "C".
+</p>
+</div>
+<div id="div">
+<span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span>
+</div>
+<div id="output">
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/dom/gc-3-expected.txt b/LayoutTests/fast/dom/gc-3-expected.txt
new file mode 100644
index 0000000..60d3a17
--- /dev/null
+++ b/LayoutTests/fast/dom/gc-3-expected.txt
@@ -0,0 +1,8 @@
+This test verifies that DOM nodes are not retained just because a wrapper exists for a descendant. A wrapper must exist for the node itself or for an ancestor.
+
+The output should be the following pieces of text on lines by themselves: "replacement content", "B", "child node exists".
+
+replacement content
+B
+child node exists
+
diff --git a/LayoutTests/fast/dom/gc-3.html b/LayoutTests/fast/dom/gc-3.html
new file mode 100644
index 0000000..880f4534
--- /dev/null
+++ b/LayoutTests/fast/dom/gc-3.html
@@ -0,0 +1,48 @@
+<head>
+<script>
+function doit()
+{
+ var B = document.getElementById("span-B");
+ B.customProperty = "B";
+
+ document.getElementById("div").innerHTML = "<span>replacement content</span>";
+
+ // create lots of objects to force a garbage collection
+ var i = 0;
+ while (i < 1000) {
+ i = i+1;
+ }
+
+ var output= document.getElementById("output");
+
+ output.innerHTML += B.customProperty + "<BR>";
+ if (B.parentNode) {
+ output.innerHTML += "parent node exists<BR>";
+ }
+ if (B.firstChild) {
+ output.innerHTML += "child node exists<BR>";
+ }
+}
+
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+}
+
+</script>
+</head>
+
+<body onload="doit()">
+<div style="border: 1px solid red">
+<p>
+This test verifies that DOM nodes are not retained just because a wrapper exists for a descendant. A wrapper must exist for the node itself or for an ancestor.
+</p>
+<p>
+The output should be the following pieces of text on lines by themselves: "replacement content", "B", "child node exists".
+</p>
+</div>
+<div id="div">
+<span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span>
+</div>
+<div id="output">
+</div>
+</body>