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">
+اردو وڑ
+<span class="quote">پروسیسرس پر</span>
+تبصر
+</div>
+
+<div contenteditable="true" id="ltr-bidi">
+preceding text
+<span class="bidi">content</span>
+following text
+</div>
+
+<div contenteditable="true" id="rtl-bidi">
+اردو وڑ
+<span class="bidi">پروسیسرس پر</span>
+تبصر
+</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/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);
}
}