Bug 989012 - Part 2: Don't get stuck when seeing an image without a src or alt attribute; r=roc
We do not want to traverse inside native anonymous elements, but we
should still be able to skip over generated content, to avoid getting
stuck on such images.
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/bug989012-3-ref.html
@@ -0,0 +1,28 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ img {
+ border: solid 1px red;
+ mid-width: 1em;
+ display: inline-block;
+ }
+ </style>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<img>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ // Set the caret right before "bar"
+ sel.collapse(div.lastChild, 0);
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/bug989012-3.html
@@ -0,0 +1,31 @@
+<html class="reftest-wait">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ img {
+ border: solid 1px red;
+ mid-width: 1em;
+ display: inline-block;
+ }
+ </style>
+ </head>
+ <body onload="start()">
+ <div onfocus="done()" contenteditable>foo<img>bar</div>
+ <script>
+ var div = document.querySelector("div");
+ function start() {
+ div.focus();
+ }
+ function done() {
+ var sel = getSelection();
+ sel.collapse(div, 0);
+ // Press Right four times to set the caret right before "bar"
+ for (var i = 0; i < 4; ++i) {
+ synthesizeKey("VK_RIGHT", {});
+ }
+ document.documentElement.removeAttribute("class");
+ }
+ </script>
+ </body>
+</html>
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -52,16 +52,18 @@ support-files =
bug570378-persian-4-ref.html
bug570378-persian-5.html
bug570378-persian-5-ref.html
bug644768.html
bug989012-1.html
bug989012-1-ref.html
bug989012-2.html
bug989012-2-ref.html
+ bug989012-3.html
+ bug989012-3-ref.html
bug1061468.html
bug1061468-ref.html
bug1109968-1-ref.html
bug1109968-1.html
bug1109968-2-ref.html
bug1109968-2.html
[test_preserve3d_sorting_hit_testing.html]
--- a/layout/base/tests/test_reftests_with_caret.html
+++ b/layout/base/tests/test_reftests_with_caret.html
@@ -104,16 +104,17 @@ function endTest() {
var tests = [
[ 'bug106855-1.html' , 'bug106855-1-ref.html' ] ,
[ 'bug106855-2.html' , 'bug106855-1-ref.html' ] ,
[ 'bug389321-2.html' , 'bug389321-2-ref.html' ] ,
[ 'bug613807-1.html' , 'bug613807-1-ref.html' ] ,
[ 'bug989012-1.html' , 'bug989012-1-ref.html' ] ,
[ 'bug989012-2.html' , 'bug989012-2-ref.html' ] ,
+ [ 'bug989012-3.html' , 'bug989012-3-ref.html' ] ,
[ 'bug1082486-1.html', 'bug1082486-1-ref.html'] ,
[ 'bug1082486-2.html', 'bug1082486-2-ref.html'] ,
// The following test cases are all involving with one sending
// synthesizeKey(), the other without. They ought to be failed
// when touch caret preference on. Test them with preference off.
function() {SpecialPowers.setBoolPref("touchcaret.enabled", false);} ,
[ 'bug240933-1.html' , 'bug240933-1-ref.html' ] ,
[ 'bug240933-2.html' , 'bug240933-1-ref.html' ] ,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -7041,20 +7041,22 @@ nsIFrame::GetFrameFromDirection(nsDirect
if (aDirection == eDirNext)
frameTraversal->Next();
else
frameTraversal->Prev();
traversedFrame = frameTraversal->CurrentItem();
- // Skip anonymous elements
+ // Skip anonymous elements, but watch out for generated content
if (!traversedFrame ||
- traversedFrame->GetContent()->IsRootOfNativeAnonymousSubtree())
+ (!traversedFrame->IsGeneratedContentFrame() &&
+ traversedFrame->GetContent()->IsRootOfNativeAnonymousSubtree())) {
return NS_ERROR_FAILURE;
+ }
traversedFrame->IsSelectable(&selectable, nullptr);
if (!selectable) {
*aOutMovedOverNonSelectableText = true;
}
} // while (!selectable)
*aOutOffset = (aDirection == eDirNext) ? 0 : -1;