Diff
Copied: branches/chromium/1025/LayoutTests/editing/selection/first-letter-selection-crash-expected.txt (from rev 110323, trunk/LayoutTests/editing/selection/first-letter-selection-crash-expected.txt) (0 => 110459)
--- branches/chromium/1025/LayoutTests/editing/selection/first-letter-selection-crash-expected.txt (rev 0)
+++ branches/chromium/1025/LayoutTests/editing/selection/first-letter-selection-crash-expected.txt 2012-03-12 19:47:16 UTC (rev 110459)
@@ -0,0 +1 @@
+PASS
Copied: branches/chromium/1025/LayoutTests/editing/selection/first-letter-selection-crash.html (from rev 110323, trunk/LayoutTests/editing/selection/first-letter-selection-crash.html) (0 => 110459)
--- branches/chromium/1025/LayoutTests/editing/selection/first-letter-selection-crash.html (rev 0)
+++ branches/chromium/1025/LayoutTests/editing/selection/first-letter-selection-crash.html 2012-03-12 19:47:16 UTC (rev 110459)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<body>
+<style>
+#test2:first-letter { display: block; }
+</style>
+<script>
+if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+
+window._onload_ = function() {
+ test1 = document.createElement('div');
+ document.body.appendChild(test1);
+ test2 = document.createElement('div');
+ test2.setAttribute('id', 'test2');
+ test2.appendChild(document.createTextNode('aaa'));
+ test2.style.display = 'inline-block';
+ test1.appendChild(test2);
+ test1.appendChild(document.createTextNode('a'));
+ document.execCommand('selectall');
+ document.body.offsetTop;
+ document.styleSheets[0].insertRule("#test2 { text-transform: uppercase }");
+ document.body.offsetTop;
+ document.body.innerHTML = "PASS";
+}
+</script>
+</body>
+</html>
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderBoxModelObject.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderBoxModelObject.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderBoxModelObject.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -224,26 +224,23 @@
return gImageQualityController;
}
-void RenderBoxModelObject::setSelectionState(SelectionState s)
+void RenderBoxModelObject::setSelectionState(SelectionState state)
{
- if (selectionState() == s)
+ if (state == SelectionInside && selectionState() != SelectionNone)
return;
-
- if (s == SelectionInside && selectionState() != SelectionNone)
- return;
- if ((s == SelectionStart && selectionState() == SelectionEnd)
- || (s == SelectionEnd && selectionState() == SelectionStart))
+ if ((state == SelectionStart && selectionState() == SelectionEnd)
+ || (state == SelectionEnd && selectionState() == SelectionStart))
RenderObject::setSelectionState(SelectionBoth);
else
- RenderObject::setSelectionState(s);
-
- // FIXME:
- // We should consider whether it is OK propagating to ancestor RenderInlines.
+ RenderObject::setSelectionState(state);
+
+ // FIXME: We should consider whether it is OK propagating to ancestor RenderInlines.
// This is a workaround for http://webkit.org/b/32123
- RenderBlock* cb = containingBlock();
- if (cb && !cb->isRenderView())
- cb->setSelectionState(s);
+ // The containing block can be null in case of an orphaned tree.
+ RenderBlock* containingBlock = this->containingBlock();
+ if (containingBlock && !containingBlock->isRenderView())
+ containingBlock->setSelectionState(state);
}
bool RenderBoxModelObject::shouldPaintAtLowQuality(GraphicsContext* context, Image* image, const void* layer, const LayoutSize& size)
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderListMarker.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderListMarker.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderListMarker.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -1694,11 +1694,12 @@
void RenderListMarker::setSelectionState(SelectionState state)
{
+ // The selection state for our containing block hierarchy is updated by the base class call.
RenderBox::setSelectionState(state);
- if (InlineBox* box = inlineBoxWrapper())
- if (RootInlineBox* root = box->root())
+
+ if (m_inlineBoxWrapper && canUpdateSelectionOnRootLineBoxes())
+ if (RootInlineBox* root = m_inlineBoxWrapper->root())
root->setHasSelectedChildren(state != SelectionNone);
- containingBlock()->setSelectionState(state);
}
LayoutRect RenderListMarker::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent)
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderObject.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderObject.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderObject.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -2786,6 +2786,12 @@
return SetCursorBasedOnStyle;
}
+bool RenderObject::canUpdateSelectionOnRootLineBoxes()
+{
+ RenderBlock* containingBlock = this->containingBlock();
+ return containingBlock ? !containingBlock->needsLayout() : true;
+}
+
#if ENABLE(SVG)
RenderSVGResourceContainer* RenderObject::toRenderSVGResourceContainer()
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderObject.h (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderObject.h 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderObject.h 2012-03-12 19:47:16 UTC (rev 110459)
@@ -764,6 +764,8 @@
// descendants (as described above in the SelectionState enum declaration).
SelectionState selectionState() const { return m_bitfields.selectionState(); }
virtual void setSelectionState(SelectionState state) { m_bitfields.setSelectionState(state); }
+ inline void setSelectionStateIfNeeded(SelectionState);
+ bool canUpdateSelectionOnRootLineBoxes();
// A single rectangle that encompasses all of the selected objects within this object. Used to determine the tightest
// possible bounding box for the selection.
@@ -1105,6 +1107,14 @@
return style()->preserveNewline();
}
+inline void RenderObject::setSelectionStateIfNeeded(SelectionState state)
+{
+ if (selectionState() == state)
+ return;
+
+ setSelectionState(state);
+}
+
inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
{
#if !ENABLE(3D_RENDERING)
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderReplaced.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderReplaced.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderReplaced.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -500,14 +500,14 @@
return IntRect(newLogicalTop, 0, root->selectionHeight(), height());
}
-void RenderReplaced::setSelectionState(SelectionState s)
+void RenderReplaced::setSelectionState(SelectionState state)
{
- RenderBox::setSelectionState(s); // The selection state for our containing block hierarchy is updated by the base class call.
- if (m_inlineBoxWrapper) {
- RootInlineBox* line = m_inlineBoxWrapper->root();
- if (line)
- line->setHasSelectedChildren(isSelected());
- }
+ // The selection state for our containing block hierarchy is updated by the base class call.
+ RenderBox::setSelectionState(state);
+
+ if (m_inlineBoxWrapper && canUpdateSelectionOnRootLineBoxes())
+ if (RootInlineBox* root = m_inlineBoxWrapper->root())
+ root->setHasSelectedChildren(isSelected());
}
bool RenderReplaced::isSelected() const
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderText.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderText.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderText.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -1134,39 +1134,41 @@
void RenderText::setSelectionState(SelectionState state)
{
- InlineTextBox* box;
-
RenderObject::setSelectionState(state);
- if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
- int startPos, endPos;
- selectionStartEnd(startPos, endPos);
- if (selectionState() == SelectionStart) {
- endPos = textLength();
- // to handle selection from end of text to end of line
- if (startPos != 0 && startPos == endPos)
- startPos = endPos - 1;
- } else if (selectionState() == SelectionEnd)
- startPos = 0;
+ if (canUpdateSelectionOnRootLineBoxes()) {
+ if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
+ int startPos, endPos;
+ selectionStartEnd(startPos, endPos);
+ if (selectionState() == SelectionStart) {
+ endPos = textLength();
- for (box = firstTextBox(); box; box = box->nextTextBox()) {
- if (box->isSelected(startPos, endPos)) {
- RootInlineBox* line = box->root();
- if (line)
- line->setHasSelectedChildren(true);
+ // to handle selection from end of text to end of line
+ if (startPos && startPos == endPos)
+ startPos = endPos - 1;
+ } else if (selectionState() == SelectionEnd)
+ startPos = 0;
+
+ for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+ if (box->isSelected(startPos, endPos)) {
+ RootInlineBox* root = box->root();
+ if (root)
+ root->setHasSelectedChildren(true);
+ }
}
+ } else {
+ for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+ RootInlineBox* root = box->root();
+ if (root)
+ root->setHasSelectedChildren(state == SelectionInside);
+ }
}
- } else {
- for (box = firstTextBox(); box; box = box->nextTextBox()) {
- RootInlineBox* line = box->root();
- if (line)
- line->setHasSelectedChildren(state == SelectionInside);
- }
}
- // The returned value can be null in case of an orphaned tree.
- if (RenderBlock* cb = containingBlock())
- cb->setSelectionState(state);
+ // The containing block can be null in case of an orphaned tree.
+ RenderBlock* containingBlock = this->containingBlock();
+ if (containingBlock && !containingBlock->isRenderView())
+ containingBlock->setSelectionState(state);
}
void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, unsigned len, bool force)
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderView.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderView.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderView.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -487,7 +487,7 @@
// Now clear the selection.
SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
- i->first->setSelectionState(SelectionNone);
+ i->first->setSelectionStateIfNeeded(SelectionNone);
// set selection start and end
m_selectionStart = start;
@@ -497,12 +497,12 @@
// Update the selection status of all objects between m_selectionStart and m_selectionEnd
if (start && start == end)
- start->setSelectionState(SelectionBoth);
+ start->setSelectionStateIfNeeded(SelectionBoth);
else {
if (start)
- start->setSelectionState(SelectionStart);
+ start->setSelectionStateIfNeeded(SelectionStart);
if (end)
- end->setSelectionState(SelectionEnd);
+ end->setSelectionStateIfNeeded(SelectionEnd);
}
RenderObject* o = start;
@@ -510,7 +510,7 @@
while (o && o != stop) {
if (o != start && o != end && o->canBeSelectionLeaf())
- o->setSelectionState(SelectionInside);
+ o->setSelectionStateIfNeeded(SelectionInside);
o = o->nextInPreOrder();
}
Modified: branches/chromium/1025/Source/WebCore/rendering/RenderWidget.cpp (110458 => 110459)
--- branches/chromium/1025/Source/WebCore/rendering/RenderWidget.cpp 2012-03-12 19:44:37 UTC (rev 110458)
+++ branches/chromium/1025/Source/WebCore/rendering/RenderWidget.cpp 2012-03-12 19:47:16 UTC (rev 110459)
@@ -359,11 +359,11 @@
void RenderWidget::setSelectionState(SelectionState state)
{
- if (selectionState() != state) {
- RenderReplaced::setSelectionState(state);
- if (m_widget)
- m_widget->setIsSelected(isSelected());
- }
+ // The selection state for our containing block hierarchy is updated by the base class call.
+ RenderReplaced::setSelectionState(state);
+
+ if (m_widget)
+ m_widget->setIsSelected(isSelected());
}
void RenderWidget::clearWidget()