Bug 1359411 - Backout bug 1328030 since it caused a hang which is strictly worse than the original problem. r=smaug, a=gchang
authorMats Palmgren <mats@mozilla.com>
Sun, 07 May 2017 22:54:18 +0200
changeset 396258 13b604cdefa40a97bb3b24bd2ec0f8ab504deb55
parent 396257 b1dd6f4104bc64aab5d093f4786caa9a91367633
child 396259 de9ea8491a29b467e2624b4de28977b199536981
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, gchang
bugs1359411, 1328030
milestone54.0
Bug 1359411 - Backout bug 1328030 since it caused a hang which is strictly worse than the original problem. r=smaug, a=gchang MozReview-Commit-ID: C12Tajtc7Vy
dom/base/test/mochitest.ini
dom/base/test/test_selection_with_anon_trees.html
layout/generic/nsFrame.cpp
mobile/android/tests/browser/robocop/testAccessibleCarets.html
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -728,18 +728,16 @@ support-files = file_receiveMessage.html
 [test_range_bounds.html]
 skip-if = toolkit == 'android'
 [test_reentrant_flush.html]
 skip-if = toolkit == 'android'
 [test_referrer_redirect.html]
 [test_root_iframe.html]
 [test_screen_orientation.html]
 [test_script_loader_crossorigin_data_url.html]
-[test_selection_with_anon_trees.html]
-skip-if = (toolkit == 'android' || asan) # bug 1330526
 [test_setInterval_uncatchable_exception.html]
 skip-if = debug == false
 [test_settimeout_extra_arguments.html]
 [test_settimeout_inner.html]
 [test_setTimeoutWith0.html]
 [test_setting_opener.html]
 [test_simplecontentpolicy.html]
 skip-if = e10s # Bug 1156489.
deleted file mode 100644
--- a/dom/base/test/test_selection_with_anon_trees.html
+++ /dev/null
@@ -1,445 +0,0 @@
-<!DOCTYPE>
-<html>
-<head>
-<title>selection over trees of anonymous nodes</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script src="/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
-<style type="text/css">
-@font-face {
-  font-family: Ahem;
-  src: url("Ahem.ttf");
-}
-* { font-family: Ahem; font-size: 20px; }
-</style>
-
-</head>
-<body>
-
-<div id="test1">
-aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa
-<table>
-  <tbody>
-    <tr>
-      <td>
-        <input value="1111">
-      </td>
-    </tr>
-  <tbody>
-</table>
-bbbbbbbb
-<br>
-<br>
-</div>
-
-<div id="test2">
-ccccc ccccccc cccccccccccc ccccccccc
-<div>
-  <input value="2222">
-</div>
-dddddd
-</div>
-
-<div id="test3">
-aaaaa
-<br>
-<input type="button"><br>
-<br>
-<input type="button"><br>
-BBBBB BB<br>
-<br>
-</div>
-
-
-<pre id="test">
-<script class="testbody" type="text/javascript">
-
-const kIsWin = navigator.platform.indexOf("Win") == 0;
-
-function test()
-{
-  function clear(w)
-  {
-    var sel = (w ? w : window).getSelection();
-    sel.removeAllRanges();
-  }
-  function doneTest(e)
-  {
-    // We hide the elements we're done with so that later tests
-    // are inside the rather narrow iframe mochitest gives us.
-    // It matters for synthesizeMouse event tests.
-    e.style.display = 'none';
-    e.offsetHeight;
-  }
-  function show(e) { e.style.display = ''; }
-
-  function dragSelectWithKey(e, clickCount, shiftKey, pointsArray)
-  {
-    const kMove = { type:"mousemove", shiftKey:shiftKey };
-    let pt = pointsArray[0];
-    let x = pt[0];
-    let y = pt[1];
-    synthesizeMouse(e, x, y, { type:"mousedown", clickCount:clickCount, shiftKey:shiftKey });
-    pointsArray.forEach(function(pt) {
-      let x = pt[0];
-      let y = pt[1];
-      synthesizeMouse(e, x, y, kMove);
-    });
-    pt = pointsArray[pointsArray.length - 1];
-    x = pt[0];
-    y = pt[1];
-    synthesizeMouse(e, x, y, kMove);
-    synthesizeMouse(e, x, y, { type:"mouseup", shiftKey:shiftKey });
-  }
-
-  function shiftDragSelect(e, clickCount, pointsArray)
-  {
-    dragSelectWithKey(e, clickCount, true, pointsArray);
-  }
-  function dragSelect(e, clickCount, pointsArray)
-  {
-    dragSelectWithKey(e, clickCount, false, pointsArray);
-  }
-
-  function shiftClick(e, x, y)
-  {
-    synthesizeMouse(e, x, y, { type: "mousedown", shiftKey: true });
-    synthesizeMouse(e, x, y, { type: "mouseup", shiftKey: true });
-  }
-
-  function click(e, x, y)
-  {
-    synthesizeMouse(e, x, y, { type: "mousedown" });
-    synthesizeMouse(e, x, y, { type: "mouseup" });
-  }
-
-  function repeatShiftKey(k, n) {
-    for (let i = 0; i < n; ++i) {
-      synthesizeKey(k, { shiftKey:true });
-    }
-  }
-
-  function init(arr, e)
-  {
-    clear();
-    var sel = window.getSelection();
-    for (i = 0; i < arr.length; ++i) {
-      var data = arr[i];
-      var r = new Range()
-      r.setStart(node(e, data[0]), data[1]);
-      r.setEnd(node(e, data[2]), data[3]);
-      sel.addRange(r);
-    }
-  }
-
-  function NL(s) { return s.replace(/(\r\n|\n\r|\r)/g, '\n'); }
-
-  function checkText(text, e)
-  {
-    var sel = window.getSelection();
-    is(NL(sel.toString()), text, e.id + ": selected text")
-  }
-
-  function checkRangeText(text, index)
-  {
-    var r = window.getSelection().getRangeAt(index);
-    is(NL(r.toString()), text, e.id + ": range["+index+"].toString()")
-  }
-
-  function node(e, arg)
-  {
-    if (typeof arg == "number")
-      return arg == -1 ? e : e.childNodes[arg];
-    return arg;
-  }
-
-  function checkRangeCount(n, e)
-  {
-    var sel = window.getSelection();
-    is(sel.rangeCount, n, e.id + ": Selection range count");
-  }
-
-  function checkRange(r, expected, e) {
-    is(r.startContainer, node(e, expected[0]), e.id + ": range["+i+"].startContainer");
-    is(r.startOffset, expected[1], e.id + ": range["+i+"].startOffset");
-    is(r.endContainer, node(e, expected[2]), e.id + ": range["+i+"].endContainer");
-    is(r.endOffset, expected[3], e.id + ": range["+i+"].endOffset");
-  }
-
-  function checkRanges(arr, e)
-  {
-    let sel = window.getSelection();
-    checkRangeCount(arr.length, e);
-    for (i = 0; i < arr.length; ++i) {
-      let expected = arr[i];
-      let r = sel.getRangeAt(i);
-      checkRange(r, expected, e);
-    }
-  }
-
-  // ======================================================
-  // ================== dragSelect tests ==================
-  // ======================================================
-
-  // Downward word-select with SHIFT
-  clear();
-  var e = document.getElementById('test1');
-  shiftDragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,110], [10,110]]);
-  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
-  checkRanges([[0,1,-1,3]], e);
-
-  // Downward word-select without SHIFT
-  clear();
-  dragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,110], [10,110]]);
-  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
-  checkRanges([[0,1,-1,3]], e);
-
-  // Downward char-select with SHIFT
-  clear();
-  click(e, 1, 1);
-  shiftDragSelect(e, 1, [[30,5], [250,5], [250,20], [250,50], [60,110], [20,110]]);
-  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nb', e);
-  checkRanges([[0,1,2,2]], e);
-
-  // Downward char-select without SHIFT
-  clear();
-  dragSelect(e, 1, [[40,5], [60,70], [30,110]]);
-  checkText('aaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nb', e);
-  checkRanges([[0,3,2,2]], e);
-
-  // Upward word-select with SHIFT
-  clear();
-  shiftDragSelect(e, 2, [[20,110], [60,110], [250,50], [250,20], [250,5], [30,5], [30,5]]);
-  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
-  checkRanges([[0,1,-1,3]], e);
-
-  // Upward word-select without SHIFT
-  clear();
-  dragSelect(e, 2, [[20,110], [60,110], [250,50], [250,20], [250,5], [30,5], [30,5]]);
-  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbbbbb ', e);
-  checkRanges([[0,1,-1,3]], e);
-
-  // Upward char-select with SHIFT
-  clear();
-  click(e, 100, 110);
-  shiftDragSelect(e, 1, [[20,110], [250,50], [250,20], [250,5], [30,5]]);
-  checkText('aaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbb', e);
-  checkRanges([[0,2,2,6]], e);
-
-  // Upward char-select without SHIFT
-  clear();
-  dragSelect(e, 1, [[30,110], [60,110], [40,5]]);
-  checkText('aaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nb', e);
-  checkRanges([[0,3,2,2]], e);
-
-  doneTest(e);
-
-  // Downward word-select with SHIFT
-  var e = document.getElementById('test2');
-  shiftDragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,100], [10,100]]);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
-  checkRanges([[0,1,2,7]], e);
-
-  // Downward word-select without SHIFT
-  clear();
-  dragSelect(e, 2, [[20,5], [30,5], [250,5], [250,20], [250,50], [60,100], [10,100]]);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
-  checkRanges([[0,1,2,7]], e);
-
-  // Downward char-select with SHIFT
-  clear();
-  click(e, 1, 1);
-  shiftDragSelect(e, 1, [[30,5], [30,5], [250,5], [250,20], [250,50], [60,100], [20,100]]);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\nd', e);
-  checkRanges([[0,1,2,2]], e);
-
-  // Downward char-select without SHIFT
-  clear();
-  dragSelect(e, 1, [[40,5], [250,5], [250,20], [250,50], [60,100], [20,100]]);
-  checkText('ccc ccccccc cccccccccccc ccccccccc\nd', e);
-  checkRanges([[0,3,2,2]], e);
-
-  // Upward word-select with SHIFT
-  var e = document.getElementById('test2');
-  shiftDragSelect(e, 2, [[10,100], [60,100], [250,50], [250,20], [250,5], [30,5], [20,5]]);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
-  checkRanges([[0,1,2,7]], e);
-
-  // Upward word-select without SHIFT
-  clear();
-  shiftDragSelect(e, 2, [[10,100], [60,100], [250,50], [250,20], [250,5], [30,5], [20,5]]);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\ndddddd', e);
-  checkRanges([[0,1,2,7]], e);
-
-  // Upward char-select with SHIFT
-  clear();
-  click(e, 100, 100);
-  shiftDragSelect(e, 1, [[20,100], [250,50], [250,20], [250,5], [60,5]]);
-  checkText('cc ccccccc cccccccccccc ccccccccc\nddddd', e);
-  checkRanges([[0,4,2,6]], e);
-
-  // Upward char-select without SHIFT
-  clear();
-  dragSelect(e, 1, [[20,100], [60,100], [60,5]]);
-  checkText('cc ccccccc cccccccccccc ccccccccc\nd', e);
-  checkRanges([[0,4,2,2]], e);
-
-  doneTest(e);
-
-  // On Windows word-selection also selects the space after the word.
-  kSpaceAfterWord = kIsWin ? ' ' : '';
-
-  // Downward word-select with SHIFT
-  e = document.getElementById('test3');
-  clear();
-  shiftDragSelect(e, 2, [[50,5], [60,125], [10,125]]);
-  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
-  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
-
-  // Downward word-select without SHIFT
-  e = document.getElementById('test3');
-  clear();
-  dragSelect(e, 2, [[40,5], [30,5], [50,5], [60,125], [10,125]]);
-  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
-  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
-
-  // Downward char-select without SHIFT
-  e = document.getElementById('test3');
-  clear();
-  dragSelect(e, 1, [[60,5], [60,125], [20,125]]);
-  checkText('aa\n\n\n\nB', e);
-  checkRanges([[0,4,-1,3], [4,0,-1,8], [9,0,10,2]], e);
-
-  // Upward word-select with SHIFT
-  e = document.getElementById('test3');
-  clear();
-  shiftDragSelect(e, 2, [[10,125], [60,125], [50,5]]);
-  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
-  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
-
-  // Upward word-select without SHIFT
-  e = document.getElementById('test3');
-  clear();
-  dragSelect(e, 2, [[40,125], [60,125], [50,5], [30,5], [20,5]]);
-  checkText('aaaaa\n\n\n\nBBBBB' + kSpaceAfterWord, e);
-  checkRanges([[0,1,-1,3], [4,0,-1,8], [9,0,10,6 + kSpaceAfterWord.length]], e);
-
-  // Upward char-select without SHIFT
-  e = document.getElementById('test3');
-  clear();
-  dragSelect(e, 1, [[60,125], [60,125], [50,5], [30,5], [40,5]]);
-  checkText('aaa\n\n\n\nBBB', e);
-  checkRanges([[0,3,-1,3], [4,0,-1,8], [9,0,10,4]], e);
-
-  doneTest(e);
-
-
-  // ======================================================
-  // ================== shift+click tests =================
-  // ======================================================
-
-  e = document.getElementById('test1');
-  show(e);
-
-  clear();
-  init([[0,0,0,1]], e);
-  shiftClick(e, 100, 100);
-  checkText(' aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbb', e);
-  checkRanges([[0,0,2,6]], e);
-  
-  clear();
-  init([[2,6,2,6]], e);
-  shiftClick(e, 60, 5);
-  checkText('aa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbbb', e);
-  checkRanges([[0,4,2,6]], e);
-  
-  doneTest(e);
-  e = document.getElementById('test2');
-  show(e);
-
-  clear();
-  init([[0,4,0,4]], e);
-  shiftClick(e, 100, 100);
-  checkText('cc ccccccc cccccccccccc ccccccccc\nddddd', e);
-  checkRanges([[0,4,2,6]], e);
-
-  clear();
-  init([[2,6,2,6]], e);
-  shiftClick(e, 1, 5);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\nddddd', e);
-  checkRanges([[0,1,2,6]], e);
-
-  doneTest(e);
-  e = document.getElementById('test3');
-  show(e);
-
-  clear();
-  init([[0,4,0,4]], e);
-  shiftClick(e, 70, 125);
-  checkText('aa\n\n\n\nBBB', e);
-  checkRanges([[0,4,-1,3], [4,0,-1,8], [9,0,10,4]], e);
-
-  // ======================================================
-  // ================== Kbd command tests =================
-  // ======================================================
-
-  doneTest(e);
-  e = document.getElementById('test1');
-  show(e);
-
-  clear();
-  init([[0,0,0,0]], e);
-  repeatShiftKey("VK_RIGHT", 45);
-  checkText(' aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbb', e);
-  checkRanges([[0,0,2,4]], e);
-
-  clear();
-  init([[2,5,2,5]], e);
-  repeatShiftKey("VK_LEFT", 45);
-  checkText('aaaaa aaaaa aaaaaaa aaaaaaaa aaaaaaaa\nbbbb', e);
-  checkRanges([[0,1,2,5]], e);
-
-  doneTest(e);
-  e = document.getElementById('test2');
-  show(e);
-
-  clear();
-  init([[0,0,0,0]], e);
-  repeatShiftKey("VK_RIGHT", 45);
-  checkText(' ccccc ccccccc cccccccccccc ccccccccc\ndddd', e);
-  checkRanges([[0,0,2,5]], e);
-
-  clear();
-  init([[2,6,2,6]], e);
-  repeatShiftKey("VK_LEFT", 45);
-  checkText('ccccc ccccccc cccccccccccc ccccccccc\nddddd', e);
-  checkRanges([[0,1,2,6]], e);
-
-  doneTest(e);
-  e = document.getElementById('test3');
-  show(e);
-
-  clear();
-  init([[0,0,0,0]], e);
-  repeatShiftKey("VK_RIGHT", 15);
-  checkText(' aaaaa\n\n\n\nBBB', e);
-  checkRanges([[0,0,-1,3], [4,0,-1,8], [9,0,10,4]], e);
-
-  clear();
-  init([[10,4,10,4]], e);
-  repeatShiftKey("VK_LEFT", 10);
-  checkText('aaaa\n\n\n\nBBB', e);
-  checkRanges([[0,2,-1,3], [4,0,-1,8], [9,0,10,4]], e);
-
-  clear();
-  SimpleTest.finish();
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(test);
-
-</script>
-</pre>
-</body>
-</html>
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -8382,37 +8382,22 @@ nsIFrame::GetFrameFromDirection(nsDirect
                                   aVisual && presContext->BidiEnabled(),
                                   aScrollViewStop,
                                   true,  // aFollowOOFs
                                   false  // aSkipPopupChecks
                                   );
     if (NS_FAILED(result))
       return result;
 
-    auto Advance = [&frameTraversal, aDirection] () {
-      if (aDirection == eDirNext) {
-        frameTraversal->Next();
-      } else {
-        frameTraversal->Prev();
-      }
-      return frameTraversal->CurrentItem();
-    };
-
-    traversedFrame = Advance();
-
-    if (nsIContent* content = GetContent()) {
-      // Advance until the frame is inside the same tree as 'this'.
-      for (nsIContent* traversedContent;
-           traversedFrame &&
-             !traversedFrame->IsGeneratedContentFrame() &&
-             (traversedContent = traversedFrame->GetContent()) &&
-             !nsContentUtils::IsInSameAnonymousTree(content, traversedContent);) {
-        traversedFrame = Advance();
-      }
-    }
+    if (aDirection == eDirNext)
+      frameTraversal->Next();
+    else
+      frameTraversal->Prev();
+
+    traversedFrame = frameTraversal->CurrentItem();
 
     // Skip anonymous elements, but watch out for generated content
     if (!traversedFrame ||
         (!traversedFrame->IsGeneratedContentFrame() &&
          traversedFrame->GetContent()->IsRootOfNativeAnonymousSubtree())) {
       return NS_ERROR_FAILURE;
     }
 
@@ -9291,41 +9276,33 @@ nsFrame::DoGetParentStyleContext(nsIFram
     return *aProviderFrame ? (*aProviderFrame)->StyleContext() : nullptr;
   }
   return placeholder->GetParentStyleContext(aProviderFrame);
 }
 
 void
 nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
 {
-  if (!aFrame || !*aFrame) {
+  if (!aFrame || !*aFrame)
     return;
-  }
-
-  nsIFrame* child = *aFrame;
-  while (true) {
+  nsIFrame *child = *aFrame;
+  //if we are a block frame then go for the last line of 'this'
+  while (1){
     child = child->PrincipalChildList().FirstChild();
-    if (!child) {
-      return; // done
-    }
-
-    // Ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
-    // see bug 278197 comment #12 #13 for details.
-    nsIFrame* nonAnonymousChild = nullptr;
-    const nsIContent* content;
-    while (child &&
-           (content = child->GetContent()) &&
-           !content->IsRootOfNativeAnonymousSubtree()) {
-      nonAnonymousChild = child;
-      child = child->GetNextSibling();
-    }
-    if (!nonAnonymousChild) {
-      return;
-    }
-    *aFrame = child = nonAnonymousChild;
+    if (!child)
+      return;//nothing to do
+    nsIFrame* siblingFrame;
+    nsIContent* content;
+    //ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
+    //see bug 278197 comment #12 #13 for details
+    while ((siblingFrame = child->GetNextSibling()) &&
+           (content = siblingFrame->GetContent()) &&
+           !content->IsRootOfNativeAnonymousSubtree())
+      child = siblingFrame;
+    *aFrame = child;
   }
 }
 
 void
 nsFrame::GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
 {
   if (!aFrame || !*aFrame)
     return;
--- a/mobile/android/tests/browser/robocop/testAccessibleCarets.html
+++ b/mobile/android/tests/browser/robocop/testAccessibleCarets.html
@@ -34,17 +34,17 @@
 
     <br>
     <input id="LTRphone" style="direction: ltr;" size="40"
       value="09876543210 .-.)(wp#*1034103410341034X">
     <br>
     <input id="RTLphone" style="direction: rtl;" size="40"
       value="התקשר +972 3 7347514 במשך זמן טוב">
     <br><br><br>
-    <div>x<input value="DDs12">3 45<em id="bug1265750"> 678</em> 90</div>
+    <div><input value="DDs12">3 45<em id="bug1265750"> 678</em> 90</div>
 
     <br><br><br>
     <tr><td>cell</td><td><p id="bug1338445-1">012345p</p></td><td>cell</td></tr>
     <br><br><br>
     <div><p>p12</p><p id="bug1338445-2">p34</p><p>p56</p></div>
     </tr>
   </body>
 </html>