Bug 868906 - Make GetChildFrameContainingOffset() stable. r=roc
authorMats Palmgren <matspal@gmail.com>
Tue, 07 May 2013 20:48:59 +0200
changeset 131160 7f1def8c39e8
parent 131159 b8e1d4abf560
child 131161 0a50d67075be
push id24649
push userryanvm@gmail.com
push dateWed, 08 May 2013 02:10:32 +0000
treeherdermozilla-central@b980d32c366f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs868906
milestone23.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 868906 - Make GetChildFrameContainingOffset() stable. r=roc
layout/base/nsDisplayList.cpp
layout/generic/crashtests/868906.html
layout/generic/crashtests/crashtests.list
layout/generic/nsTextFrameThebes.cpp
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -792,16 +792,18 @@ nsDisplayListBuilder::EnterPresShell(nsI
     buildCaret = false;
   }
 
   if (!buildCaret)
     return;
 
   nsRefPtr<nsCaret> caret = state->mPresShell->GetCaret();
   state->mCaretFrame = caret->GetCaretFrame();
+  NS_ASSERTION(state->mCaretFrame == caret->GetCaretFrame(),
+               "GetCaretFrame() is unstable");
 
   if (state->mCaretFrame) {
     // Check if the dirty rect intersects with the caret's dirty rect.
     nsRect caretRect =
       caret->GetCaretRect() + state->mCaretFrame->GetOffsetTo(aReferenceFrame);
     if (caretRect.Intersects(aDirtyRect)) {
       // Okay, our rects intersect, let's mark the frame and all of its ancestors.
       mFramesMarkedForDisplay.AppendElement(state->mCaretFrame);
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/868906.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<meta charset="UTF-8">
+<script>
+
+function boom()
+{
+  var root = document.documentElement;
+  while(root.firstChild) { root.removeChild(root.firstChild); }
+  root.appendChild(document.createElement("body"));
+  root.offsetHeight;
+
+  var bigText = document.createTextNode("");
+  bigText.data += "\u202D";
+  bigText.data += "A";
+  bigText.data += "\x1C";
+  bigText.data += "\u062A";
+  bigText.data += "E";
+  bigText.data += "\u062E";
+  bigText.data += " ";
+  bigText.data += "\u202D";
+  bigText.data += "X";
+  bigText.data += "\x1C";
+  bigText.data += "Y";
+  root.appendChild(bigText);
+
+  var smallText = document.createTextNode("Z");
+  root.appendChild(smallText);
+
+  root.focus();
+
+  function del()
+  {
+    var range = document.createRange();
+    range.setStart(root, 0);
+    range.setEnd(bigText, bigText.data.length);
+    range.deleteContents();
+  }
+
+  del();
+
+  function finish() {
+    document.documentElement.removeAttribute('class');
+  }
+
+  setTimeout(finish, 0);
+}
+
+</script>
+</head>
+
+<body onload="boom();"></body>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -456,9 +456,10 @@ test-pref(layout.css.flexbox.enabled,tru
 load 847130.xhtml
 load 847208.html
 asserts(4) load 847209.html # bug 847368
 test-pref(layout.css.flexbox.enabled,true) load 847211-1.html
 load 849603.html
 test-pref(layout.css.flexbox.enabled,true) load 851396-1.html
 test-pref(layout.css.flexbox.enabled,true) load 854263-1.html
 test-pref(layout.css.flexbox.enabled,true) load 862947-1.html
+needs-focus pref(accessibility.browsewithcaret,true) load 868906.html
 test-pref(layout.css.flexbox.enabled,true) load 866547-1.html
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -6340,29 +6340,35 @@ nsTextFrame::GetChildFrameContainingOffs
       (aHint || aContentOffset != offset)) {
     while (true) {
       nsTextFrame* next = static_cast<nsTextFrame*>(f->GetNextContinuation());
       if (!next || aContentOffset < next->GetContentOffset())
         break;
       if (aContentOffset == next->GetContentOffset()) {
         if (aHint) {
           f = next;
+          if (f->GetContentLength() == 0) {
+            continue; // use the last of the empty frames with this offset
+          }
         }
         break;
       }
       f = next;
     }
   } else {
     while (true) {
       nsTextFrame* prev = static_cast<nsTextFrame*>(f->GetPrevContinuation());
       if (!prev || aContentOffset > f->GetContentOffset())
         break;
       if (aContentOffset == f->GetContentOffset()) {
         if (!aHint) {
           f = prev;
+          if (f->GetContentLength() == 0) {
+            continue; // use the first of the empty frames with this offset
+          }
         }
         break;
       }
       f = prev;
     }
   }
   
   *aOutOffset = aContentOffset - f->GetContentOffset();