Index: src/wp-admin/js/editor-expand.js
===================================================================
--- src/wp-admin/js/editor-expand.js	(revision 37574)
+++ src/wp-admin/js/editor-expand.js	(working copy)
@@ -15,7 +15,10 @@
 			$visualEditor = $(),
 			$textTop = $( '#ed_toolbar' ),
 			$textEditor = $( '#content' ),
+			textEditor = $textEditor[0],
+			textEditorLength = 0,
 			$textEditorClone = $( '<div id="content-textarea-clone" class="wp-exclude-emoji"></div>' ),
+			textEditorClonelineHeight = parseInt( $textEditor.css( 'line-height' ), 10 ),
 			$bottom = $( '#post-status-info' ),
 			$menuBar = $(),
 			$statusBar = $(),
@@ -87,65 +90,50 @@
 		function textEditorKeyup( event ) {
 			var VK = jQuery.ui.keyCode,
 				key = event.keyCode,
-				range = document.createRange(),
-				selStart = $textEditor[0].selectionStart,
-				selEnd = $textEditor[0].selectionEnd,
-				textNode = $textEditorClone[0].firstChild,
 				buffer = 10,
-				offset, cursorTop, cursorBottom, editorTop, editorBottom;
+				offset, cursorTop, editorTop;
 
-			if ( selStart && selEnd && selStart !== selEnd ) {
+			if ( key !== VK.UP && key !== VK.LEFT && key !== VK.BACKSPACE ) {
 				return;
 			}
 
-			// These are not TinyMCE ranges.
-			try {
-				range.setStart( textNode, selStart );
-				range.setEnd( textNode, selEnd + 1 );
-			} catch ( ex ) {}
-
-			offset = range.getBoundingClientRect();
-
-			if ( ! offset.height ) {
-				return;
-			}
+			$textEditorClone.width( $textEditor.width() - 22 );
+			$textEditorClone.text( $textEditor.val().substring( 0, $textEditor[0].selectionStart ) || '&nbsp;' );
 
-			cursorTop = offset.top - buffer;
-			cursorBottom = cursorTop + offset.height + buffer;
+			offset = $textEditorClone[0].getBoundingClientRect();
+			cursorTop = offset.bottom + textEditorClonelineHeight - buffer;
 			editorTop = heights.adminBarHeight + heights.toolsHeight + heights.textTopHeight;
-			editorBottom = heights.windowHeight - heights.bottomHeight;
 
-			if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
+			if ( cursorTop < editorTop ) {
 				window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop );
-			} else if ( cursorBottom > editorBottom ) {
-				window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom );
 			}
 		}
 
 		function textEditorResize() {
+			var pageYOffset, height,
+				reduce = textEditorLength && textEditorLength > textEditor.value.length;
+
 			if ( ( mceEditor && ! mceEditor.isHidden() ) || ( ! mceEditor && initialMode === 'tinymce' ) ) {
 				return;
 			}
 
-			var textEditorHeight = $textEditor.height(),
-				hiddenHeight;
+			textEditorLength = textEditor.value.length;
+			height = textEditor.style.height;
 
-			$textEditorClone.width( $textEditor.width() - 22 );
-			$textEditorClone.text( $textEditor.val() + '&nbsp;' );
+			if ( reduce ) {
+				pageYOffset = window.pageYOffset;
 
-			hiddenHeight = $textEditorClone.height();
+				textEditor.style.height = 'auto';
+				textEditor.style.height = textEditor.scrollHeight + 'px';
 
-			if ( hiddenHeight < autoresizeMinHeight ) {
-				hiddenHeight = autoresizeMinHeight;
+				window.scrollTo( window.pageXOffset, pageYOffset );
+			} else if ( parseInt( textEditor.style.height, 10 ) < textEditor.scrollHeight ) {
+				textEditor.style.height = textEditor.scrollHeight + 'px';
 			}
 
-			if ( hiddenHeight === textEditorHeight ) {
-				return;
+			if ( height !== textEditor.style.height ) {
+				adjust();
 			}
-
-			$textEditor.height( hiddenHeight );
-
-			adjust();
 		}
 
 		// We need to wait for TinyMCE to initialize.
@@ -474,7 +462,7 @@
 
 					if ( event && event.deltaHeight > 0 && event.deltaHeight < 100 ) {
 						window.scrollBy( 0, event.deltaHeight );
-					} else if ( advanced ) {
+					} else if ( visual && advanced ) {
 						fixedBottom = true;
 
 						$statusBar.css( {
