[Pkg-javascript-commits] [dojo] 84/87: Fixes #16975. Remove leak when calling empty() on SVG elements (all browsers). On IE, use removeChild instead of removeNode on SVG elements since they don't inherit removeNode from HTMLElement and SVG/removeNode is incorrectly implemented. Backport thru 1.6. Add additional strict and quirks automated tests to make sure empty() and destroy() are working correctly with SVG and OBJECT nodes, and since these element's behavior seem dependent on the document's compatMode. !strict

David Prévot taffit at moszumanska.debian.org
Thu Aug 21 17:39:25 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to annotated tag 1.7.5
in repository dojo.

commit 5479e319a3ff550b3707bb4e76e2c3d5a11fb0b7
Author: Douglas Hays <doughays at dojotoolkit.org>
Date:   Wed Apr 10 12:05:48 2013 +0000

    Fixes #16975.  Remove leak when calling empty() on SVG elements (all browsers).  On IE, use removeChild instead of removeNode on SVG elements since they don't inherit removeNode from HTMLElement and SVG/removeNode is incorrectly implemented.  Backport thru 1.6.  Add additional strict and quirks automated tests to make sure empty() and destroy() are working correctly with SVG and OBJECT nodes, and since these element's behavior seem dependent on the document's compatMode. !strict
    
    git-svn-id: http://svn.dojotoolkit.org/src/branches/1.7/dojo@31197 560b804f-0ae3-0310-86f3-f6aa0a117693
---
 dom-construct.js             | 30 ++++++++++----------
 tests/_base/html.html        | 65 ++++++++++++++++++++++++++++++++++++++++++--
 tests/_base/html_quirks.html | 63 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 18 deletions(-)

diff --git a/dom-construct.js b/dom-construct.js
index a5f6361..0bac44a 100644
--- a/dom-construct.js
+++ b/dom-construct.js
@@ -340,22 +340,22 @@ define(["exports", "./_base/kernel", "./_base/sniff", "./_base/window", "./dom",
 		return tag; // DomNode
 	};
 
-	var _empty =
-		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
-		has("ie") ?
-		function(/*DomNode*/ node){
+	function _empty(/*DomNode*/ node){
+		if(node.canHaveChildren){
 			try{
-				node.innerHTML = ""; // really fast when it works
-			}catch(e){ // IE can generate Unknown Error
-				for(var c; c = node.lastChild;){ // intentional assignment
-					_destroy(c, node); // destroy is better than removeChild so TABLE elements are removed in proper order
-				}
+				// fast path
+				node.innerHTML = "";
+				return;
+			}catch(e){
+				// innerHTML is readOnly (e.g. TABLE (sub)elements in quirks mode)
+				// Fall through (saves bytes)
 			}
-		} :
-		//>>excludeEnd("webkitMobile");
-		function(/*DomNode*/ node){
-			node.innerHTML = "";
-		};
+		}
+		// SVG/strict elements don't support innerHTML/canHaveChildren, and OBJECT/APPLET elements in quirks node have canHaveChildren=false
+		for(var c; c = node.lastChild;){ // intentional assignment
+			_destroy(c, node); // destroy is better than removeChild so TABLE subelements are removed in proper order
+		}
+	}
 
 	exports.empty = function empty(/*DOMNode|String*/ node){
 		_empty(dom.byId(node));
@@ -369,7 +369,7 @@ define(["exports", "./_base/kernel", "./_base/sniff", "./_base/window", "./dom",
 		if(parent){
 			//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 			// removeNode(false) doesn't leak in IE 6+, but removeChild() and removeNode(true) are known to leak under IE 8- while 9+ is TBD
-			has("ie") && 'removeNode' in node ? node.removeNode(false) :
+			has("ie") && parent.canHaveChildren && 'removeNode' in node ? node.removeNode(false) :
 			//>>excludeEnd("webkitMobile");
 				parent.removeChild(node);
 		}
diff --git a/tests/_base/html.html b/tests/_base/html.html
index a9444ee..509de64 100644
--- a/tests/_base/html.html
+++ b/tests/_base/html.html
@@ -622,6 +622,48 @@
 					});
 				});
 
+				doh.register("t",
+					[
+						function emptySvg(t){
+							dojo.empty(dojo.byId("surface"));
+							doh.f(!!dojo.byId("surface").firstChild, "svg firstChild");
+						},
+						function destroySvg(t){
+							dojo.destroy(dojo.byId("surface"));
+							doh.f(!!dojo.byId("surface"), "svg byId");
+						},
+						function emptyObject(t){
+							dojo.empty(dojo.byId("objectToEmpty"));
+							doh.f(!!dojo.byId("objectToEmpty").firstChild, "object firstChild");
+						},
+						function destroyObject(t){
+							dojo.destroy(dojo.byId("objectToEmpty"));
+							doh.f(!!dojo.byId("objectToEmpty"), "object byId");
+						},
+						function destroyIframe(t){
+							dojo.destroy(dojo.byId("iframeToDestroy"));
+							doh.f(!!dojo.byId("iframeToDestroy"), "iframe byId");
+						},
+						function destroyDivNotInDOM(t){
+							var p = dojo.byId("divToRemoveFromDOM");
+							var n = dojo.byId("divToDestroy");
+							p = p.parentNode.removeChild(p);
+							doh.f(!!dojo.byId("divToRemoveFromDOM"), "div byId");
+							doh.t(!!p.firstChild, "div child 1");
+							doh.is(p.firstChild, n, "div 1st child");
+							doh.isNot(p.firstChild, p.lastChild, "div 1st child");
+							dojo.destroy(n);
+							doh.t(!!p.firstChild, "div child 2");
+							doh.isNot(p.firstChild, n, "div 2nd child");
+							doh.is(p.firstChild, p.lastChild, "div 2nd child");
+							dojo.empty(p);
+							doh.f(!!p.firstChild, "div child 3");
+							dojo.destroy(p);
+							doh.t(true, "no exception thrown");
+						}
+					]
+				);
+
 				doh.runOnLoad();
 			});
 		</script>
@@ -859,8 +901,25 @@
 		<div id="iframeContainer"></div>
 
 		<!-- SVG element to test dojo.getComputedStyle on IE9 (#14103) -->
-		<svg id="surface" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
-			<rect id="rect1" fill="rgb(255, 0, 0)" x="0" y="0" width="80" height="60" ry="0" rx="0" fill-rule="evenodd"/>
-		</svg>
+		<!-- SVG element to test empty -->
+		<svg id="surface" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px"
+			><rect id="rect1" fill="rgb(255, 0, 0)" x="0" y="0" width="80" height="60" ry="0" rx="0" fill-rule="evenodd"
+		/></svg>
+
+		<!-- OBJECT element to test empty -->
+		<object width="500" height="500" id="objectToEmpty" data="data:application/x-silverlight," type="application/x-silverlight"
+			><param name="background" value="transparent"
+		/></object>
+
+		<!-- IFRAME element to test destroy -->
+		<iframe id="iframeToDestroy" src="about:blank"
+			><span></span
+		></iframe>
+
+		<!-- DIV element to test destroy of element not in the DOM -->
+		<div id="divToRemoveFromDOM"
+			><div id="divToDestroy"></div
+			><div></div
+		></div>
 	</body>
 </html>
diff --git a/tests/_base/html_quirks.html b/tests/_base/html_quirks.html
index 6be2f73..0f1942d 100644
--- a/tests/_base/html_quirks.html
+++ b/tests/_base/html_quirks.html
@@ -135,6 +135,48 @@
 					);
 				}
 
+				doh.register("t",
+					[
+						function emptySvg(t){
+							dojo.empty(dojo.byId("surface"));
+							doh.f(!!dojo.byId("surface").firstChild, "svg firstChild");
+						},
+						function destroySvg(t){
+							dojo.destroy(dojo.byId("surface"));
+							doh.f(!!dojo.byId("surface"), "svg byId");
+						},
+						function emptyObject(t){
+							dojo.empty(dojo.byId("objectToEmpty"));
+							doh.f(!!dojo.byId("objectToEmpty").firstChild, "object firstChild");
+						},
+						function destroyObject(t){
+							dojo.destroy(dojo.byId("objectToEmpty"));
+							doh.f(!!dojo.byId("objectToEmpty"), "object byId");
+						},
+						function destroyIframe(t){
+							dojo.destroy(dojo.byId("iframeToDestroy"));
+							doh.f(!!dojo.byId("iframeToDestroy"), "iframe byId");
+						},
+						function destroyDivNotInDOM(t){
+							var p = dojo.byId("divToRemoveFromDOM");
+							var n = dojo.byId("divToDestroy");
+							p = p.parentNode.removeChild(p);
+							doh.f(!!dojo.byId("divToRemoveFromDOM"), "div byId");
+							doh.t(!!p.firstChild, "div child 1");
+							doh.is(p.firstChild, n, "div 1st child");
+							doh.isNot(p.firstChild, p.lastChild, "div 1st child");
+							dojo.destroy(n);
+							doh.t(!!p.firstChild, "div child 2");
+							doh.isNot(p.firstChild, n, "div 2nd child");
+							doh.is(p.firstChild, p.lastChild, "div 2nd child");
+							dojo.empty(p);
+							doh.f(!!p.firstChild, "div child 3");
+							dojo.destroy(p);
+							doh.t(true, "no exception thrown");
+						}
+					]
+				);
+
 				doh.runOnLoad();
 			});
 		</script>
@@ -323,6 +365,27 @@
 		<div id="sq100nopos">
 			100px square, no positioning
 		</div>
+
+		<!-- SVG element to test empty -->
+		<svg id="surface" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px"
+			><rect id="rect1" fill="rgb(255, 0, 0)" x="0" y="0" width="80" height="60" ry="0" rx="0" fill-rule="evenodd"
+		/></svg>
+
+		<!-- OBJECT element to test empty -->
+		<object width="500" height="500" id="objectToEmpty" data="data:application/x-silverlight," type="application/x-silverlight"
+			><param name="background" value="transparent"
+		/></object>
+
+		<!-- IFRAME element to test destroy -->
+		<iframe id="iframeToDestroy" src="about:blank"
+			><span></span
+		></iframe>
+
+		<!-- DIV element to test destroy of element not in the DOM -->
+		<div id="divToRemoveFromDOM"
+			><div id="divToDestroy"></div
+			><div></div
+		></div>
 	</body>
 </html>
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/dojo.git



More information about the Pkg-javascript-commits mailing list