Title: [97597] trunk
Revision
97597
Author
commit-qu...@webkit.org
Date
2011-10-17 02:18:35 -0700 (Mon, 17 Oct 2011)

Log Message

when CSS pseudo selectors are applied (:before and :after) the *-of-line keyboard navigation does not work
https://bugs.webkit.org/show_bug.cgi?id=10123

Patch by Rosen Dash <rosen.d...@motorola.com> on 2011-10-17
Reviewed by Ryosuke Niwa.

Source/WebCore:

This patch addresses folllowing two issues:
1. When CSS pseudo elements are before or after is used with content attribute containing single character
   at the start/end of text and we try to move cursor by right navigation key, the page freezes falling
   into an infinite loop.
2. When these elements try to insert some text between a text line, navigation by right/left arrow key is prohibited.

Tests: editing/selection/css-pseudo-element-hang.html
       editing/selection/css-pseudo-element.html

* editing/VisiblePosition.cpp:
(WebCore::VisiblePosition::leftVisuallyDistinctCandidate):
(WebCore::VisiblePosition::rightVisuallyDistinctCandidate):

LayoutTests:

* editing/selection/css-pseudo-element-expected.txt: Added.
* editing/selection/css-pseudo-element-hang-expected.txt: Added.
* editing/selection/css-pseudo-element-hang.html: Added.
* editing/selection/css-pseudo-element.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (97596 => 97597)


--- trunk/LayoutTests/ChangeLog	2011-10-17 09:15:12 UTC (rev 97596)
+++ trunk/LayoutTests/ChangeLog	2011-10-17 09:18:35 UTC (rev 97597)
@@ -1,3 +1,15 @@
+2011-10-17  Rosen Dash  <rosen.d...@motorola.com>
+
+        when CSS pseudo selectors are applied (:before and :after) the *-of-line keyboard navigation does not work
+        https://bugs.webkit.org/show_bug.cgi?id=10123
+
+        Reviewed by Ryosuke Niwa.
+
+        * editing/selection/css-pseudo-element-expected.txt: Added.
+        * editing/selection/css-pseudo-element-hang-expected.txt: Added.
+        * editing/selection/css-pseudo-element-hang.html: Added.
+        * editing/selection/css-pseudo-element.html: Added.
+
 2011-10-15  Antti Koivisto  <an...@apple.com>
 
         Test :visited pseudo class

Added: trunk/LayoutTests/editing/selection/css-pseudo-element-expected.txt (0 => 97597)


--- trunk/LayoutTests/editing/selection/css-pseudo-element-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/css-pseudo-element-expected.txt	2011-10-17 09:18:35 UTC (rev 97597)
@@ -0,0 +1,34 @@
+To manually test select text below by mouse and use right arrow key to navigate across the quotes. The caret should move to the right of quote.
+
+preceding text content following text
+اردو وڑ پروسیسرس پر تبصر
+preceding text content following text
+اردو وڑ پروسیسرس پر تبصر
+PASS 1 is 1
+PASS 16 is 16
+PASS 1 is 1
+PASS 7 is 7
+PASS 1 is 1
+PASS 9 is 9
+PASS 8 is 8
+PASS 9 is 9
+PASS 1 is 1
+PASS 11 is 11
+PASS 10 is 10
+PASS 11 is 11
+PASS 1 is 1
+PASS 16 is 16
+PASS 1 is 1
+PASS 7 is 7
+PASS 10 is 10
+PASS 9 is 9
+PASS 8 is 8
+PASS 9 is 9
+PASS 1 is 1
+PASS 11 is 11
+PASS 1 is 1
+PASS 11 is 11
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/selection/css-pseudo-element-hang-expected.txt (0 => 97597)


--- trunk/LayoutTests/editing/selection/css-pseudo-element-hang-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/css-pseudo-element-hang-expected.txt	2011-10-17 09:18:35 UTC (rev 97597)
@@ -0,0 +1,10 @@
+This webpage should not hang when we try to move beyond the quotes.
+
+content
+acontenta
+content
+acontenta
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/selection/css-pseudo-element-hang.html (0 => 97597)


--- trunk/LayoutTests/editing/selection/css-pseudo-element-hang.html	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/css-pseudo-element-hang.html	2011-10-17 09:18:35 UTC (rev 97597)
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href=""
+<style type="text/css"> /* pertinent to test cases */
+.quote:before { content: "*"; }
+.quote:after { content: "*"; }
+
+.bidi:before { content: "aפb"; }
+.bidi:after { content: "aפb"; }
+</style>
+<script src=""
+<title></title>
+</head>
+<body>
+<p>This webpage should not hang when we try to move beyond the quotes.</p>
+
+<div contenteditable="true" id="test1">
+<span class="quote">content</span>
+</div>
+
+<div contenteditable="true" id="test2">
+a<span class="quote">content</span>a
+</div>
+
+<div contenteditable="true" id="test3">
+<span class="bidi">content</span>
+</div>
+
+<div contenteditable="true" id="test4">
+a<span class="bidi">content</span>a
+</div>
+
+<div id="console"></div>
+<script>
+
+var edit = document.getElementById('test1');
+edit.focus();
+
+for (var i = 0; i < 9; ++i) 
+    window.getSelection().modify('move', 'right', 'character');
+
+for (var i = 0; i < 9; ++i)
+    window.getSelection().modify('move', 'left', 'character');
+
+var edit = document.getElementById('test2');
+edit.focus();
+
+for (var i = 0; i < 11; ++i)
+    window.getSelection().modify('move', 'right', 'character');
+
+for (var i = 0; i < 11; ++i)
+    window.getSelection().modify('move', 'left', 'character');
+
+var edit = document.getElementById('test3');
+edit.focus();
+
+for (var i = 0; i < 9; ++i) 
+    window.getSelection().modify('move', 'right', 'character');
+
+for (var i = 0; i < 9; ++i)
+    window.getSelection().modify('move', 'left', 'character');
+
+var edit = document.getElementById('test4');
+edit.focus();
+
+for (var i = 0; i < 11; ++i)
+    window.getSelection().modify('move', 'right', 'character');
+
+for (var i = 0; i < 11; ++i)
+    window.getSelection().modify('move', 'left', 'character');
+
+var successfullyParsed = true;
+
+</script>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/editing/selection/css-pseudo-element.html (0 => 97597)


--- trunk/LayoutTests/editing/selection/css-pseudo-element.html	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/css-pseudo-element.html	2011-10-17 09:18:35 UTC (rev 97597)
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href=""
+<style type="text/css"> /* pertinent to test cases */
+ .quote:before { content: "\""; }
+ .quote:after { content: "\""; }
+ 
+ .bidi:before { content: "aפb"; }
+ .bidi:after { content: "aפb"; }
+</style>
+<script src=""
+<title></title>
+</head>
+<body>
+<p>To manually test select text below by mouse and use right arrow key to navigate across the quotes. The caret should move to the right of quote.</p>
+
+<div contenteditable="true" id="ltr">
+preceding text
+<span class="quote">content</span>
+following text
+</div>
+
+<div contenteditable="true" id="rtl">
+&#1575;&#1585;&#1583;&#1608; &#1608;&#1681;
+<span class="quote">&#1662;&#1585;&#1608;&#1587;&#1740;&#1587;&#1585;&#1587; &#1662;&#1585;</span>
+&#1578;&#1576;&#1589;&#1585;
+</div>
+
+<div contenteditable="true" id="ltr-bidi">
+preceding text
+<span class="bidi">content</span>
+following text
+</div>
+
+<div contenteditable="true" id="rtl-bidi">
+&#1575;&#1585;&#1583;&#1608; &#1608;&#1681;
+<span class="bidi">&#1662;&#1585;&#1608;&#1587;&#1740;&#1587;&#1585;&#1587; &#1662;&#1585;</span>
+&#1578;&#1576;&#1589;&#1585;
+</div>
+<div id="console"></div>
+<script>
+
+var edit = document.getElementById('ltr');
+edit.focus();
+window.getSelection().setPosition(edit, 1);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 16);
+
+window.getSelection().setPosition(edit, 2);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 7);
+
+var edit = document.getElementById('rtl');
+edit.focus();
+window.getSelection().setPosition(edit, 1);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 9);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 8);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 9);
+
+window.getSelection().setPosition(edit, 2);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 11);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 10);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 11);
+
+var edit = document.getElementById('ltr-bidi');
+edit.focus();
+window.getSelection().setPosition(edit, 1);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 16);
+
+window.getSelection().setPosition(edit, 2);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 7);
+
+var edit = document.getElementById('rtl-bidi');
+edit.focus();
+window.getSelection().setPosition(edit, 1);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 10);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 9);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 8);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 9);
+
+window.getSelection().setPosition(edit, 2);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 11);
+window.getSelection().modify('move', 'left', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 1);
+window.getSelection().modify('move', 'right', 'character');
+shouldEvaluateTo(window.getSelection().anchorOffset.toString(), 11);
+
+var successfullyParsed = true;
+
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (97596 => 97597)


--- trunk/Source/WebCore/ChangeLog	2011-10-17 09:15:12 UTC (rev 97596)
+++ trunk/Source/WebCore/ChangeLog	2011-10-17 09:18:35 UTC (rev 97597)
@@ -1,3 +1,23 @@
+2011-10-17  Rosen Dash  <rosen.d...@motorola.com>
+
+        when CSS pseudo selectors are applied (:before and :after) the *-of-line keyboard navigation does not work
+        https://bugs.webkit.org/show_bug.cgi?id=10123
+
+        Reviewed by Ryosuke Niwa.
+
+        This patch addresses folllowing two issues:
+        1. When CSS pseudo elements are before or after is used with content attribute containing single character
+           at the start/end of text and we try to move cursor by right navigation key, the page freezes falling
+           into an infinite loop.
+        2. When these elements try to insert some text between a text line, navigation by right/left arrow key is prohibited.
+
+        Tests: editing/selection/css-pseudo-element-hang.html
+               editing/selection/css-pseudo-element.html
+
+        * editing/VisiblePosition.cpp:
+        (WebCore::VisiblePosition::leftVisuallyDistinctCandidate):
+        (WebCore::VisiblePosition::rightVisuallyDistinctCandidate):
+
 2011-10-15  Antti Koivisto  <an...@apple.com>
 
         Test :visited pseudo class

Modified: trunk/Source/WebCore/editing/VisiblePosition.cpp (97596 => 97597)


--- trunk/Source/WebCore/editing/VisiblePosition.cpp	2011-10-17 09:15:12 UTC (rev 97596)
+++ trunk/Source/WebCore/editing/VisiblePosition.cpp	2011-10-17 09:18:35 UTC (rev 97597)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Portions Copyright (c) 2011 Motorola Mobility, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -125,6 +126,15 @@
             if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset())
                 return box->isLeftToRightDirection() ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
 
+            if (!renderer->node()) {
+                box = box->prevLeafChild();
+                if (!box)
+                    return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
+                renderer = box->renderer();
+                offset = box->caretRightmostOffset();
+                continue;
+            }
+
             offset = box->isLeftToRightDirection() ? renderer->previousOffset(offset) : renderer->nextOffset(offset);
 
             int caretMinOffset = box->caretMinOffset();
@@ -192,6 +202,9 @@
                 continue;
             }
 
+            while (prevBox && !prevBox->renderer()->node())
+                prevBox = prevBox->prevLeafChild();
+
             if (prevBox) {
                 box = prevBox;
                 renderer = box->renderer();
@@ -234,6 +247,8 @@
 
         if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
             return p;
+
+        ASSERT(p != m_deepPosition);
     }
 }
 
@@ -276,6 +291,15 @@
             if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset())
                 return box->isLeftToRightDirection() ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
 
+            if (!renderer->node()) {
+                box = box->nextLeafChild();
+                if (!box)
+                    return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
+                renderer = box->renderer();
+                offset = box->caretLeftmostOffset();
+                continue;
+            }
+
             offset = box->isLeftToRightDirection() ? renderer->nextOffset(offset) : renderer->previousOffset(offset);
 
             int caretMinOffset = box->caretMinOffset();
@@ -322,6 +346,7 @@
                     }
                     break;
                 }
+
                 if (nextBox->bidiLevel() >= level)
                     break;
 
@@ -344,10 +369,14 @@
                 continue;
             }
 
+            while (nextBox && !nextBox->renderer()->node())
+                nextBox = nextBox->nextLeafChild();
+
             if (nextBox) {
                 box = nextBox;
                 renderer = box->renderer();
                 offset = box->caretLeftmostOffset();
+
                 if (box->bidiLevel() > level) {
                     do {
                         nextBox = nextBox->nextLeafChild();
@@ -386,6 +415,8 @@
 
         if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
             return p;
+
+        ASSERT(p != m_deepPosition);
     }
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to