Bug 1381710 - Selection.addRange will be failed with dynamic table insertion. r?mats draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Tue, 18 Jul 2017 16:54:31 +0900
changeset 620164 b9edc0180bd4c23d17127fa987107dcc294c5000
parent 620112 d942ef54fdf726840a698d2ddcaf989d2c00edbc
child 640609 22800e5f2d2bb635f9e7cab2f3c8089901a760f8
push id71942
push userbmo:m_kato@ga2.so-net.ne.jp
push dateThu, 03 Aug 2017 06:13:59 +0000
reviewersmats
bugs1381710
milestone57.0a1
Bug 1381710 - Selection.addRange will be failed with dynamic table insertion. r?mats When range is selected table element, Selection.addRange uses nsFrameSelection. If frame isn't constructed yet, addRange throws NS_ERROR_FAILURE even if table element isn't editable element. When getting nsITableCellLayout, we should flush frame to construct cell frame. MozReview-Commit-ID: 9qWwW46RYNL
dom/base/Selection.cpp
layout/generic/test/mochitest.ini
layout/generic/test/test_bug1381710.html
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -646,20 +646,25 @@ Selection::GetTableCellLocationFromRange
   nsCOMPtr<nsIContent> content = do_QueryInterface(aRange->GetStartContainer());
   if (!content)
     return NS_ERROR_FAILURE;
 
   nsIContent *child = content->GetChildAt(aRange->StartOffset());
   if (!child)
     return NS_ERROR_FAILURE;
 
+  // GetCellLayout depends on current frame, we need flush frame to get
+  // nsITableCellLayout
+  nsCOMPtr<nsIPresShell> presShell = mFrameSelection->GetShell();
+  if (presShell) {
+    presShell->FlushPendingNotifications(FlushType::Frames);
+  }
+
   //Note: This is a non-ref-counted pointer to the frame
   nsITableCellLayout *cellLayout = mFrameSelection->GetCellLayout(child);
-  if (NS_FAILED(result))
-    return result;
   if (!cellLayout)
     return NS_ERROR_FAILURE;
 
   return cellLayout->GetCellIndexes(*aRow, *aCol);
 }
 
 nsresult
 Selection::AddTableCellRange(nsRange* aRange, bool* aDidAddRange,
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -92,16 +92,17 @@ support-files = bug633762_iframe.html
 [test_bug904810.html]
 [test_bug938772.html]
 [test_bug970363.html]
 [test_bug1062406.html]
 [test_bug1174521.html]
 [test_bug1198135.html]
 [test_bug1307853.html]
 support-files = file_bug1307853.html
+[test_bug1381710.html]
 [test_contained_plugin_transplant.html]
 skip-if = os=='win'
 [test_image_selection.html]
 [test_image_selection_2.html]
 [test_invalidate_during_plugin_paint.html]
 skip-if = toolkit == 'android'
 [test_intrinsic_size_on_loading.html]
 [test_movement_by_characters.html]
new file mode 100644
--- /dev/null
+++ b/layout/generic/test/test_bug1381710.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1381710
+-->
+<head>
+  <title>Test for Mozilla Bug 1381710</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1381710">Mozilla Bug 1381710</a>
+<div id="content">
+  <div id="nonedit"></div>
+  <div id="edit" contenteditable=true></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+function test(element)
+{
+  let selection = window.getSelection();
+  selection.removeAllRanges();
+  let range = document.createRange();
+
+  element.innerHTML = "<table><tr id=tr><td id=td>A</td><td>B</td><tr></table>";
+  let td = document.getElementById("td");
+  range.selectNode(td);
+  // Don't throw exception
+  selection.addRange(range);
+  is(selection.anchorNode, document.getElementById("tr"),
+     "anchor node should be <TR> element");
+  element.innerHTML = "";
+}
+
+test(document.getElementById("nonedit"));
+test(document.getElementById("edit"));
+</script>
+</pre>
+</body>
+</html>