Bug 951943 - SelectionHandler._updateCacheForSelection() Error: TypeError: rects[0] is undefined, r=margaret
authorMark Capella <markcapella@twcny.rr.com>
Sat, 11 Jan 2014 01:51:27 -0500
changeset 162981 69a6c6c99c85ea48fcf1fb371e1f80b24acc7b49
parent 162980 5ae12ca85cdc5821d4c5fe54c88e26e8de8927dc
child 162982 ee80588ead207d49d962c890b7a8ce8b6571ce23
push id25977
push userttaubert@mozilla.com
push dateSun, 12 Jan 2014 09:26:17 +0000
treeherdermozilla-central@b029e8d3e130 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmargaret
bugs951943
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 951943 - SelectionHandler._updateCacheForSelection() Error: TypeError: rects[0] is undefined, r=margaret
mobile/android/chrome/content/SelectionHandler.js
--- a/mobile/android/chrome/content/SelectionHandler.js
+++ b/mobile/android/chrome/content/SelectionHandler.js
@@ -120,33 +120,46 @@ var SelectionHandler = {
         break;
       }
       case "TextSelection:Position": {
         if (this._activeType == this.TYPE_SELECTION) {
           // Ignore selectionChange notifications when handle movement starts
           this._ignoreSelectionChanges = true;
           // Check to see if the handles should be reversed.
           let isStartHandle = JSON.parse(aData).handleType == this.HANDLE_TYPE_START;
-          let selectionReversed = this._updateCacheForSelection(isStartHandle);
-          if (selectionReversed) {
-            // Reverse the anchor and focus to correspond to the new start and end handles.
-            let selection = this._getSelection();
-            let anchorNode = selection.anchorNode;
-            let anchorOffset = selection.anchorOffset;
-            selection.collapse(selection.focusNode, selection.focusOffset);
-            selection.extend(anchorNode, anchorOffset);
+
+          try {
+            let selectionReversed = this._updateCacheForSelection(isStartHandle);
+            if (selectionReversed) {
+              // Reverse the anchor and focus to correspond to the new start and end handles.
+              let selection = this._getSelection();
+              let anchorNode = selection.anchorNode;
+              let anchorOffset = selection.anchorOffset;
+              selection.collapse(selection.focusNode, selection.focusOffset);
+              selection.extend(anchorNode, anchorOffset);
+            }
+          } catch (e) {
+            // User finished handle positioning with one end off the screen
+            this._closeSelection();
+            break;
           }
+
           // Act on selectionChange notifications after handle movement ends
           this._ignoreSelectionChanges = false;
+          this._positionHandles();
 
         } else if (this._activeType == this.TYPE_CURSOR) {
           // Act on IMM composition notifications after caret movement ends
           this._ignoreCompositionChanges = false;
+          this._positionHandles();
+
+        } else {
+          Cu.reportError("Ignored \"TextSelection:Position\" message during invalid selection status");
         }
-        this._positionHandles();
+
         break;
       }
 
       case "TextSelection:Get":
         sendMessageToJava({
           type: "TextSelection:Data",
           requestId: aData,
           text: this._getSelectedText()
@@ -738,18 +751,22 @@ var SelectionHandler = {
             aX - offset.x < rangeRect.right + radius.right &&
             aY - offset.y > rangeRect.top - radius.top &&
             aY - offset.y < rangeRect.bottom + radius.bottom);
   },
 
   // Returns true if the selection has been reversed. Takes optional aIsStartHandle
   // param to decide whether the selection has been reversed.
   _updateCacheForSelection: function sh_updateCacheForSelection(aIsStartHandle) {
-    let selection = this._getSelection();
-    let rects = selection.getRangeAt(0).getClientRects();
+    let rects = this._getSelection().getRangeAt(0).getClientRects();
+    if (!rects[0]) {
+      // nsISelection object exists, but there's nothing actually selected
+      throw "Failed to update cache for invalid selection";
+    }
+
     let start = { x: this._isRTL ? rects[0].right : rects[0].left, y: rects[0].bottom };
     let end = { x: this._isRTL ? rects[rects.length - 1].left : rects[rects.length - 1].right, y: rects[rects.length - 1].bottom };
 
     let selectionReversed = false;
     if (this._cache.start) {
       // If the end moved past the old end, but we're dragging the start handle, then that handle should become the end handle (and vice versa)
       selectionReversed = (aIsStartHandle && (end.y > this._cache.end.y || (end.y == this._cache.end.y && end.x > this._cache.end.x))) ||
                           (!aIsStartHandle && (start.y < this._cache.start.y || (start.y == this._cache.start.y && start.x < this._cache.start.x)));