You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/05/13 19:17:53 UTC

svn commit: r943940 - in /tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5: tapestry-console.js tapestry.js

Author: hlship
Date: Thu May 13 17:17:53 2010
New Revision: 943940

URL: http://svn.apache.org/viewvc?rev=943940&view=rev
Log:
TAP5-1147: Ajax updates under IE leak lots of memory

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry-console.js
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry-console.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry-console.js?rev=943940&r1=943939&r2=943940&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry-console.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry-console.js Thu May 13 17:17:53 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -72,13 +72,13 @@ Tapestry.Logging = {
             var effect = new Effect.Fade(div, { delay: Tapestry.CONSOLE_DURATION,
                 afterFinish: function()
                 {
-                    div.remove();
+            		Tapestry.remove(div);
                 }});
 
             div.observe("click", function()
             {
                 effect.cancel();
-                div.remove();
+        		Tapestry.remove(div);
             });
         }
                 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js?rev=943940&r1=943939&r2=943940&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tapestry.js Thu May 13 17:17:53 2010
@@ -1,4 +1,4 @@
-// Copyright 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2007, 2008, 2009, 2010 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -134,7 +134,7 @@ var Tapestry = {
 			new Effect.Fade(overlay, {
 				duration : 0.2,
 				afterFinish : function() {
-					overlay.remove();
+					Tapestry.remove(overlay);
 				}
 			});
 		};
@@ -576,7 +576,6 @@ var Tapestry = {
 		var dummy = document.createElement('html');
 		dummy.appendChild(element.cloneNode(true));
 		var outerHTML = dummy.innerHTML;
-		dummy.innerHTML = '';
 
 		var replaceHTML = outerHTML.replace(new RegExp("^<" + tag, "i"),
 				"<" + newTagName).replace(new RegExp("</" + tag + ">$", "i"),
@@ -584,7 +583,69 @@ var Tapestry = {
 
 		element.insert( {
 			before : replaceHTML
-		}).remove();
+		});
+
+		Tapestry.remove(element);
+	},
+
+	/**
+	 * Removes an element and all of its direct and indirect children. The
+	 * element is first purged, to ensure that Internet Explorer doesn't leak
+	 * memory if event handlers associated with the element (or its children)
+	 * have references back to the element.
+	 * 
+	 * @since 5.2.0
+	 */
+	remove : function(element) {
+		Tapestry.purge(element);
+
+		element.remove();
+	},
+
+	/**
+	 * Purges the element of any event handlers (necessary in IE to ensure that
+	 * memory leaks do not occur, and harmless in other browsers). The element
+	 * is purged, then any children of the element are purged.
+	 */
+	purge : function(element) {
+
+		/* Adapted from http://javascript.crockford.com/memory/leak.html */
+		var attrs = element.attributes;
+		if (attrs) {
+			var l = attrs.length, i, name;
+			for (i = 0; i < l; i++) {
+				name = attrs[i].name;
+				/* Looking for onclick, etc. */
+				if (typeof element[name] == 'function') {
+					element[name] = null;
+				}
+			}
+		}
+
+		/* Get rid of any Prototype event handlers as well. */
+		Event.stopObserving(element);
+
+		Tapestry.purgeChildren(element);
+	},
+
+	/**
+	 * Invokes purge() on all the children of the element.
+	 */
+	purgeChildren : function(element) {
+
+		var children = element.childNodes;
+
+		if (children) {
+			var l = children.length, i, child;
+
+			for (i = 0; i < l; i++) {
+				var child = children[i];
+
+				/* Just purge element nodes, not text, etc. */
+				if (child.nodeType == 1)
+					Tapestry.purge(children[i]);
+			}
+		}
 	}
 };
 
@@ -848,7 +909,7 @@ Tapestry.Initializer = {
 				var effect = Tapestry.ElementEffect.fade(container);
 
 				effect.options.afterFinish = function() {
-					container.remove();
+					Tapestry.remove(container);
 				}
 			};
 
@@ -1039,7 +1100,7 @@ Tapestry.Initializer = {
 			var effect = runAnimation(false);
 
 			effect.options.afterFinish = function() {
-				element.remove();
+				Tapestry.remove(element);
 			};
 		});
 
@@ -1649,6 +1710,9 @@ Tapestry.ZoneManager = Class.create( {
 	 * @param content
 	 */
 	show : function(content) {
+
+		Tapestry.purgeChildren(this.updateElement);
+
 		this.updateElement.update(content);
 
 		var func = this.element.visible() ? this.updateFunc : this.showFunc;
@@ -1954,36 +2018,18 @@ Tapestry.ScriptManager = {
 };
 
 /**
- * In the spirit of $(), $T() exists to access the <em>Tapestry object</em>
- * for the element. The Tapestry object is used to store additional values
- * related to the element; it is simply an anonymous object stored as property
- * <code>_tapestry</code> of the element, created the first time it is
- * accessed.
- * <p>
- * This mechanism acts as a namespace, and so helps prevent name conflicts that
- * would occur if properties were stored directly on DOM elements, and makes
- * debugging a bit easier (the Tapestry-specific properties are all in one
- * place!). For the moment, added methods are stored directly on the object, and
- * are not prefixed in any way, valueing readability over preventing naming
- * conflicts.
- * <p>
- * However, this technique is being phased out and will soon be deprecated as it
- * is all too easy to cause memory cycles and leaks (especially in IE).
+ * In the spirit of $(), $T() exists to access a hash of extra data about an
+ * element. In release 5.1 and prior, a hash attached to the element by
+ * Tapestry was returned. In 5.2, Prototype's storage object is returned, which
+ * is less like to cause memory leaks in IE.
  * 
+ * @deprecated With no specific replacement
  * @param element
  *            an element instance or element id
- * @return object Tapestry object for the element
+ * @return object Prototype storage object for the element
  */
 function $T(element) {
-	var e = $(element);
-	var t = e._tapestry;
-
-	if (!t) {
-		t = {};
-		e._tapestry = t;
-	}
-
-	return t;
+	return $(element).getStorage();
 }
 
 Tapestry.onDOMLoaded(Tapestry.onDomLoadedCallback);