Bug 1435123 - HTMLEditor::GetBlock() has to specify given ancestor limit node to HTMLEditor::GetBlockNodeParent() r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 29 Mar 2018 18:57:57 +0900
changeset 774753 da19dd20a96317ac9ea01b886455ffbb4dfd05ec
parent 774751 fc96217ac1437cb960a0e5442b65a5685af5dfc2
push id104493
push usermasayuki@d-toybox.com
push dateThu, 29 Mar 2018 14:15:32 +0000
reviewersm_kato
bugs1435123
milestone61.0a1
Bug 1435123 - HTMLEditor::GetBlock() has to specify given ancestor limit node to HTMLEditor::GetBlockNodeParent() r?m_kato This is a simple bug of internal API of HTMLEditor. HTMLEditor::GetBlock() tries to retrieve nearest ancestor block node (including itself) of a node. HTMLEditor::GetBlock() may have ancestor limiter typically it's active editing host to prevent to modify editing host or its ancestor accidentally. However, it forgets to call HTMLEditor::GetBlockNodeParent() with the given ancestor limit node. Therefore, if editing host is an inline element and its parent is a block element, the editing host is split accidentally. MozReview-Commit-ID: Ermmxdnk4KB
editor/libeditor/HTMLEditor.cpp
editor/libeditor/tests/mochitest.ini
editor/libeditor/tests/test_insertParagraph_in_inline_editing_host.html
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -894,17 +894,17 @@ HTMLEditor::GetBlock(nsINode& aNode,
   MOZ_ASSERT(!aAncestorLimiter ||
              &aNode == aAncestorLimiter ||
              EditorUtils::IsDescendantOf(aNode, *aAncestorLimiter),
              "aNode isn't in aAncestorLimiter");
 
   if (NodeIsBlockStatic(&aNode)) {
     return aNode.AsElement();
   }
-  return GetBlockNodeParent(&aNode);
+  return GetBlockNodeParent(&aNode, aAncestorLimiter);
 }
 
 /**
  * IsNextCharInNodeWhitespace() checks the adjacent content in the same node to
  * see if following selection is whitespace or nbsp.
  */
 void
 HTMLEditor::IsNextCharInNodeWhitespace(nsIContent* aContent,
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -266,16 +266,17 @@ subsuite = clipboard
 [test_documentCharacterSet.html]
 [test_dom_input_event_on_htmleditor.html]
 skip-if = toolkit == 'android' # bug 1054087
 [test_dom_input_event_on_texteditor.html]
 [test_dragdrop.html]
 skip-if = os == 'android'
 [test_inline_style_cache.html]
 [test_inlineTableEditing.html]
+[test_insertParagraph_in_inline_editing_host.html]
 [test_keypress_untrusted_event.html]
 [test_objectResizing.html]
 [test_root_element_replacement.html]
 [test_select_all_without_body.html]
 [test_spellcheck_pref.html]
 skip-if = toolkit == 'android'
 [test_backspace_vs.html]
 [test_css_chrome_load_access.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_insertParagraph_in_inline_editing_host.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test "insertParagraph" command in inline editing host</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+
+<span contenteditable>foobar</span>
+<hr>
+<p><span contenteditable>foobar</span></p>
+<hr>
+<div><span contenteditable>foobar</span></div>
+<hr>
+<div contenteditable><p contenteditable="false"><span contenteditable>foobar</span></p></div>
+
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+
+<pre id="test">
+</pre>
+
+<script class="testbody" type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(() => {
+  var selection = document.getSelection();
+  var editors = document.querySelectorAll("span[contenteditable]");
+
+  var editor = editors.item(0);
+  editor.focus();
+  selection.collapse(editor.firstChild, 3);
+  document.execCommand("insertParagraph", false);
+  is(editor.innerHTML, "foo<br>bar",
+     "insertParagraph should insert <br> element (inline editing host is in <body>)");
+
+  editor = editors.item(1);
+  editor.focus();
+  selection.collapse(editor.firstChild, 3);
+  document.execCommand("insertParagraph", false);
+  is(editor.parentNode.innerHTML, "<span contenteditable=\"\">foo<br>bar</span>",
+     "insertParagraph should insert <br> element (inline editing host is in <p>)");
+
+  editor = editors.item(2);
+  editor.focus();
+  selection.collapse(editor.firstChild, 3);
+  document.execCommand("insertParagraph", false);
+  is(editor.parentNode.innerHTML, "<span contenteditable=\"\">foo<br>bar</span>",
+     "insertParagraph should insert <br> element (inline editing host is in <div>)");
+
+  editor = editors.item(3);
+  editor.focus();
+  selection.collapse(editor.firstChild, 3);
+  document.execCommand("insertParagraph", false);
+  is(editor.parentNode.parentNode.innerHTML, "<p contenteditable=\"false\"><span contenteditable=\"\">foo<br>bar</span></p>",
+     "insertParagraph should insert <br> element (inline editing host is in <p contenteditable=\"false\"> in <div contenteditable>)");
+
+  SimpleTest.finish();
+});
+
+</script>
+</body>
+
+</html>