Index: _source/core/dom/domobject.js
===================================================================
--- _source/core/dom/domobject.js	(revision 5229)
+++ _source/core/dom/domobject.js	(working copy)
@@ -115,6 +115,26 @@
 					delete nativeListeners[ eventName ];
 				}
 			}
+		},
+
+		/**
+		 * Removes any listener set on this object.
+		 * To avoid memory leaks we must assure that there are no
+		 * references left after the object is no longer needed.
+		 */
+		removeAllListeners : function()
+		{
+			var nativeListeners = this.getCustomData( '_cke_nativeListeners' );
+			for ( eventName in nativeListeners)
+			{
+				var listener = nativeListeners[ eventName ];
+				if ( this.$.removeEventListener )
+					this.$.removeEventListener( eventName, listener, false );
+				else if ( this.$.detachEvent )
+					this.$.detachEvent( 'on' + eventName, listener );
+
+				delete nativeListeners[ eventName ];
+			}
 		}
 	};
 })();
@@ -197,6 +217,22 @@
 	};
 
 	/**
+	 * Removes any data stored on this object.
+	 * To avoid memory leaks we must assure that there are no
+	 * references left after the object is no longer needed.
+	 * @name CKEDITOR.dom.domObject.prototype.clearCustomData
+	 * @function
+	 */
+	domObjectProto.clearCustomData = function()
+	{
+		// Clear all event listeners
+		this.removeAllListeners();
+
+		var expandoNumber = this.$._cke_expando;
+		expandoNumber && delete customData[ expandoNumber ];
+	};
+
+	/**
 	 * @name CKEDITOR.dom.domObject.prototype.getCustomData
 	 */
 	domObjectProto.getUniqueId = function()
Index: _source/core/editor.js
===================================================================
--- _source/core/editor.js	(revision 5229)
+++ _source/core/editor.js	(working copy)
@@ -468,7 +468,41 @@
 			if ( !noUpdate )
 				this.updateElement();
 
+			if ( this.mode )
+			{
+				var holderElement = this.getThemeSpace( 'contents' ),
+					currentMode = this._.modes[ editor.mode ];
+				currentMode.unload( holderElement );
+			}
+
 			this.theme.destroy( this );
+
+			var toolbars,
+				index, j, items;
+
+			if (this.toolbox)
+			{
+				toolbars = this.toolbox.toolbars;
+				for( index = 0; index < toolbars.length ; index++ )
+				{
+					items = toolbars[ index ].items;
+					for ( j = 0; j<items.length ; j++)
+					{
+						var instance = items[ j ];
+						if ( instance.clickFn ) CKEDITOR.tools.removeFunction( instance.clickFn );
+						if ( instance.keyDownFn ) CKEDITOR.tools.removeFunction( instance.keyDownFn );
+
+						if ( instance.index ) CKEDITOR.ui.button._.instances[ instance.index ] = null;
+					}
+				}
+			}
+
+			if (this.contextMenu)
+				CKEDITOR.tools.removeFunction( this.contextMenu._.functionId );
+
+			if (this._.filebrowserFn)
+				CKEDITOR.tools.removeFunction( this._.filebrowserFn );
+
 			this.fire( 'destroy' );
 			CKEDITOR.remove( this );
 			CKEDITOR.fire( 'instanceDestroyed', null, this );
Index: _source/core/imagecacher.js
===================================================================
--- _source/core/imagecacher.js	(revision 5229)
+++ _source/core/imagecacher.js	(working copy)
@@ -11,6 +11,7 @@
 	{
 		var doCallback = function()
 			{
+				img.removeAllListeners();
 				loaded[ image ] = 1;
 				callback();
 			};
Index: _source/plugins/button/plugin.js
===================================================================
--- _source/plugins/button/plugin.js	(revision 5229)
+++ _source/plugins/button/plugin.js	(working copy)
@@ -69,9 +69,13 @@
 	 */
 	render : function( editor, output )
 	{
-		var env = CKEDITOR.env;
+		var env = CKEDITOR.env,
+			id = this._.id = 'cke_' + CKEDITOR.tools.getNextNumber(),
+			classes = '',
+			command = this.command, // Get the command name.
+			clickFn,
+			index;
 
-		var id = this._.id = 'cke_' + CKEDITOR.tools.getNextNumber();
 		this._.editor = editor;
 
 		var instance =
@@ -90,15 +94,10 @@
 			}
 		};
 
-		var clickFn = CKEDITOR.tools.addFunction( instance.execute, instance );
+		instance.clickFn = clickFn = CKEDITOR.tools.addFunction( instance.execute, instance );
 
-		var index = CKEDITOR.ui.button._.instances.push( instance ) - 1;
+		instance.index = index = CKEDITOR.ui.button._.instances.push( instance ) - 1;
 
-		var classes = '';
-
-		// Get the command name.
-		var command = this.command;
-
 		if ( this.modes )
 		{
 			editor.on( 'mode', function()
Index: _source/plugins/filebrowser/plugin.js
===================================================================
--- _source/plugins/filebrowser/plugin.js	(revision 5229)
+++ _source/plugins/filebrowser/plugin.js	(working copy)
@@ -378,22 +378,22 @@
 		init : function( editor, pluginPath )
 		{
 			editor._.filebrowserFn = CKEDITOR.tools.addFunction( setUrl, editor );
+		}
+	} );
 
-			CKEDITOR.on( 'dialogDefinition', function( evt )
+	CKEDITOR.on( 'dialogDefinition', function( evt )
+	{
+		var definition = evt.data.definition,
+			element;
+		// Associate filebrowser to elements with 'filebrowser' attribute.
+		for ( var i in definition.contents )
+		{
+			element = definition.contents[ i ] ;
+			attachFileBrowser( evt.editor, evt.data.name, definition, element.elements );
+			if ( element.hidden && element.filebrowser )
 			{
-				var definition = evt.data.definition,
-					element;
-				// Associate filebrowser to elements with 'filebrowser' attribute.
-				for ( var i in definition.contents )
-				{
-					element = definition.contents[ i ] ;
-					attachFileBrowser( evt.editor, evt.data.name, definition, element.elements );
-					if ( element.hidden && element.filebrowser )
-					{
-						element.hidden = !isConfigured( definition, element[ 'id' ], element.filebrowser );
-					}
-				}
-			} );
+				element.hidden = !isConfigured( definition, element[ 'id' ], element.filebrowser );
+			}
 		}
 	} );
 
Index: _source/plugins/resize/plugin.js
===================================================================
--- _source/plugins/resize/plugin.js	(revision 5229)
+++ _source/plugins/resize/plugin.js	(working copy)
@@ -55,6 +55,8 @@
 					}
 				} );
 
+			editor.on( 'destroy', function() { CKEDITOR.tools.removeFunction( mouseDownFn ) } );
+
 			editor.on( 'themeSpace', function( event )
 				{
 					if ( event.data.space == 'bottom' )
Index: _source/plugins/richcombo/plugin.js
===================================================================
--- _source/plugins/richcombo/plugin.js	(revision 5229)
+++ _source/plugins/richcombo/plugin.js	(working copy)
@@ -130,7 +130,7 @@
 					var element = CKEDITOR.document.getById( id ).getChild( 1 );
 					element.focus();
 				},
-				execute : clickFn
+				clickFn : clickFn
 			};
 
 			editor.on( 'mode', function()
@@ -161,6 +161,9 @@
 					ev.preventDefault();
 				});
 
+			// For clean up
+			instance.keyDownFn = keyDownFn;
+
 			output.push(
 				'<span class="cke_rcombo">',
 				'<span id=', id );
Index: _source/plugins/showborders/plugin.js
===================================================================
--- _source/plugins/showborders/plugin.js	(revision 5229)
+++ _source/plugins/showborders/plugin.js	(working copy)
@@ -129,36 +129,33 @@
 					}
 				} );
 			}
+		}
+	});
 
-			// Table dialog must be aware of it.
-			CKEDITOR.on( 'dialogDefinition', function( ev )
-				{
-					if ( ev.editor != editor )
-						return;
+	// Table dialog must be aware of it.
+	CKEDITOR.on( 'dialogDefinition', function( ev )
+	{
+		var dialogName = ev.data.name;
 
-					var dialogName = ev.data.name;
+		if ( dialogName == 'table' || dialogName == 'tableProperties' )
+		{
+			var dialogDefinition = ev.data.definition,
+				infoTab = dialogDefinition.getContents( 'info' ),
+				borderField = infoTab.get( 'txtBorder' ),
+				originalCommit = borderField.commit;
 
-					if ( dialogName == 'table' || dialogName == 'tableProperties' )
+			borderField.commit = CKEDITOR.tools.override( originalCommit, function( org )
+			{
+				return function( data, selectedTable )
 					{
-						var dialogDefinition = ev.data.definition,
-							infoTab = dialogDefinition.getContents( 'info' ),
-							borderField = infoTab.get( 'txtBorder' ),
-							originalCommit = borderField.commit;
-
-						borderField.commit = CKEDITOR.tools.override( originalCommit, function( org )
-						{
-							return function( data, selectedTable )
-								{
-									org.apply( this, arguments );
-									var value = parseInt( this.getValue(), 10 );
-									selectedTable[ ( !value || value <= 0 ) ? 'addClass' : 'removeClass' ]( showBorderClassName );
-								};
-						} );
-					}
-				});
+						org.apply( this, arguments );
+						var value = parseInt( this.getValue(), 10 );
+						selectedTable[ ( !value || value <= 0 ) ? 'addClass' : 'removeClass' ]( showBorderClassName );
+					};
+			} );
 		}
-
 	});
+
 } )();
 
 /**
Index: _source/plugins/sourcearea/plugin.js
===================================================================
--- _source/plugins/sourcearea/plugin.js	(revision 5229)
+++ _source/plugins/sourcearea/plugin.js	(working copy)
@@ -138,6 +138,7 @@
 
 						unload : function( holderElement )
 						{
+							textarea.clearCustomData();
 							editor.textarea = textarea = null;
 
 							if ( onResize )
Index: _source/plugins/toolbar/plugin.js
===================================================================
--- _source/plugins/toolbar/plugin.js	(revision 5229)
+++ _source/plugins/toolbar/plugin.js	(working copy)
@@ -284,6 +284,10 @@
 									editor.execCommand( 'toolbarCollapse' );
 								} );
 
+							editor.on( 'destroy', function () {
+									CKEDITOR.tools.removeFunction( collapserFn );
+								} );
+
 							var collapserId = 'cke_' + CKEDITOR.tools.getNextNumber();
 
 							editor.addCommand( 'toolbarCollapse',
Index: _source/plugins/wysiwygarea/plugin.js
===================================================================
--- _source/plugins/wysiwygarea/plugin.js	(revision 5229)
+++ _source/plugins/wysiwygarea/plugin.js	(working copy)
@@ -691,6 +691,12 @@
 
 							unload : function( holderElement )
 							{
+								editor.document.getDocumentElement().clearCustomData();
+								editor.document.getBody().clearCustomData();
+
+								editor.window.clearCustomData();
+								editor.document.clearCustomData();
+
 								editor.window = editor.document = iframe = mainElement = isPendingFocus = null;
 
 								editor.fire( 'contentDomUnload' );
@@ -759,6 +765,10 @@
 							editor.focus();
 						} );
 				} );
+				editor.on( 'destroy', function()
+				{
+					ieFocusGrabber.clearCustomData();
+				} );
 			}
 		}
 	});
Index: _source/themes/default/theme.js
===================================================================
--- _source/themes/default/theme.js	(revision 5229)
+++ _source/themes/default/theme.js	(working copy)
@@ -229,6 +229,8 @@
 		destroy : function( editor )
 		{
 			var container = editor.container;
+			container.clearCustomData();
+			editor.element.clearCustomData();
 
 			/*
 			 * IE BUG: Removing the editor DOM elements while the selection is inside
@@ -256,10 +258,9 @@
 				container.remove();
 
 			if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE )
-			{
 				editor.element.show();
-				delete editor.element;
-			}
+
+			delete editor.element;
 		}
 	};
 })() );
