Index: wp-admin/includes/class-wp-upgrader.php
===================================================================
--- wp-admin/includes/class-wp-upgrader.php	(revision 41427)
+++ wp-admin/includes/class-wp-upgrader.php	(working copy)
@@ -323,6 +323,37 @@
 	}
 
 	/**
+	 * Flatten the results of $wp_filesystem->dirlist
+	 *
+	 * @param  array &$_flat_files  New array of files to be built, passed by reference.
+	 * @param  array $_files        Array of files as returned from WP_Filesystem->dirlist
+	 * @param  string $path         Path to prepend to child arrays, optional
+	 */
+	private function _flatten_dir_list( &$_flat_files, $_files, $path = '' ) {
+	    foreach ( $_files as $file ) {
+
+	        //The dirlist command returns the filename as both a parent array key
+	        //as well as a named key within the child array, use that for simplicity
+	        $name = $file[ 'name' ];
+
+	        //Append the current file with the supplied relative path
+	        $_flat_files[ $path . $name ] = $file;
+
+	        //Make sure we've got a sub-array of files
+	        if ( array_key_exists( 'files', $file ) && is_array( $file[ 'files' ] ) && count( $file[ 'files' ]  > 0 ) ) {
+
+	            //Iterate over the sub files and folders
+	            foreach ( $file['files'] as $details ) {
+
+	                //flatten_dir_list expects the second
+	                $this->_flatten_dir_list( $_flat_files, array( $details ), $path . $name . '/' );
+	            }
+	        }
+
+	    }
+	}
+
+	/**
 	 * Clears the directory where this item is going to be installed into.
 	 *
 	 * @since 4.3.0
@@ -335,31 +366,23 @@
 	public function clear_destination( $remote_destination ) {
 		global $wp_filesystem;
 
-		if ( ! $wp_filesystem->exists( $remote_destination ) ) {
+		$_files = $wp_filesystem->dirlist( $remote_destination, true, true );
+
+		//dirlist() returns false if the directory doesn't exist
+		if ( false === $_files ) {
 			return true;
 		}
 
+		//Will hold a flattened version of $_files
+        $_flat_files = array();
+
+        $this->_flatten_dir_list( $_flat_files, $_files );
+
 		// Check all files are writable before attempting to clear the destination.
 		$unwritable_files = array();
 
-		$_files = $wp_filesystem->dirlist( $remote_destination, true, true );
-
-		// Flatten the resulting array, iterate using each as we append to the array during iteration.
-		while ( $f = each( $_files ) ) {
-			$file = $f['value'];
-			$name = $f['key'];
-
-			if ( ! isset( $file['files'] ) ) {
-				continue;
-			}
-
-			foreach ( $file['files'] as $filename => $details ) {
-				$_files[ $name . '/' . $filename ] = $details;
-			}
-		}
-
 		// Check writability.
-		foreach ( $_files as $filename => $file_details ) {
+		foreach ( $_flat_files as $filename => $file_details ) {
 			if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
 
 				// Attempt to alter permissions to allow writes and try again.
