- Revision
- 120896
- Author
- [email protected]
- Date
- 2012-06-20 18:34:11 -0700 (Wed, 20 Jun 2012)
Log Message
Source/WebCore: [Shadow][Editing] Deleting character in distributed element caused a crash.
https://bugs.webkit.org/show_bug.cgi?id=88484
Reviewed by Ryosuke Niwa.
If we mutate nodes which are children of a shadow host, it causes
ElementShadow::invalidateDistribution(). As a result, shadow host
is detached (and lazyAttached()) and its renderer is gone. That
causes assertion error since isEditablePosition() assumes
anchorNode's style was correctly calculated.
This patch makes isEditablePosition() call
document->updateLayoutIgnorePendingStylesheets() so that it does
not return a bogus result.
There is an exceptional caller of isEditablePosition,
RenderBlock::paintCaret(), from where we can not call
updateLayout() in isEditablePosition because it hits assertion,
ASSERT(!isPainting). So I've added the third parameter to
isEditablePosition to control updating the style.
Test: edition/shadow/delete-characters-in-distributed-node.html
* editing/FrameSelection.h:
(WebCore::FrameSelection::rendererIsEditable):
* editing/VisibleSelection.cpp:
(WebCore::VisibleSelection::rendererIsEditable):
(WebCore):
* editing/VisibleSelection.h:
(VisibleSelection):
* editing/htmlediting.cpp:
(WebCore::isEditablePosition):
* editing/htmlediting.h:
(WebCore):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintCaret):
LayoutTests: [Shadow][Editing] Deleting character in distributed element caused a crash
https://bugs.webkit.org/show_bug.cgi?id=88484
Reviewed by Ryosuke Niwa.
* editing/shadow/delete-characters-in-distributed-node-crash-expected.txt: Added.
* editing/shadow/delete-characters-in-distributed-node-crash.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (120895 => 120896)
--- trunk/LayoutTests/ChangeLog 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/LayoutTests/ChangeLog 2012-06-21 01:34:11 UTC (rev 120896)
@@ -1,3 +1,13 @@
+2012-06-20 Hayato Ito <[email protected]>
+
+ [Shadow][Editing] Deleting character in distributed element caused a crash
+ https://bugs.webkit.org/show_bug.cgi?id=88484
+
+ Reviewed by Ryosuke Niwa.
+
+ * editing/shadow/delete-characters-in-distributed-node-crash-expected.txt: Added.
+ * editing/shadow/delete-characters-in-distributed-node-crash.html: Added.
+
2012-06-20 Kent Tamura <[email protected]>
Unmodified form control value are overwritten by another form
Added: trunk/LayoutTests/editing/shadow/delete-characters-in-distributed-node-crash-expected.txt (0 => 120896)
--- trunk/LayoutTests/editing/shadow/delete-characters-in-distributed-node-crash-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/shadow/delete-characters-in-distributed-node-crash-expected.txt 2012-06-21 01:34:11 UTC (rev 120896)
@@ -0,0 +1,4 @@
+This tests the deletion of text in distributed node does not crash. To run it outside of DRT, you must delete text, 'foo', manually.
+
+
+PASS
Added: trunk/LayoutTests/editing/shadow/delete-characters-in-distributed-node-crash.html (0 => 120896)
--- trunk/LayoutTests/editing/shadow/delete-characters-in-distributed-node-crash.html (rev 0)
+++ trunk/LayoutTests/editing/shadow/delete-characters-in-distributed-node-crash.html 2012-06-21 01:34:11 UTC (rev 120896)
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p id="description">This tests the deletion of text in distributed node does not crash. To run it outside of DRT, you must delete text, 'foo', manually.</p>
+<div id="shadowhost" contenteditable><div>foo</div></div>
+<script>
+if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+var shadowRoot = new WebKitShadowRoot(document.getElementById('shadowhost'));
+shadowRoot.innerHTML = "<content></content>";
+
+var textNode = document.getElementById('shadowhost').firstChild.firstChild;
+window.getSelection().setBaseAndExtent(textNode, 0, textNode, 3);
+document.execCommand('Delete');
+
+document.write('PASS');
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (120895 => 120896)
--- trunk/Source/WebCore/ChangeLog 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/ChangeLog 2012-06-21 01:34:11 UTC (rev 120896)
@@ -1,3 +1,42 @@
+2012-06-20 Hayato Ito <[email protected]>
+
+ [Shadow][Editing] Deleting character in distributed element caused a crash.
+ https://bugs.webkit.org/show_bug.cgi?id=88484
+
+ Reviewed by Ryosuke Niwa.
+
+ If we mutate nodes which are children of a shadow host, it causes
+ ElementShadow::invalidateDistribution(). As a result, shadow host
+ is detached (and lazyAttached()) and its renderer is gone. That
+ causes assertion error since isEditablePosition() assumes
+ anchorNode's style was correctly calculated.
+
+ This patch makes isEditablePosition() call
+ document->updateLayoutIgnorePendingStylesheets() so that it does
+ not return a bogus result.
+
+ There is an exceptional caller of isEditablePosition,
+ RenderBlock::paintCaret(), from where we can not call
+ updateLayout() in isEditablePosition because it hits assertion,
+ ASSERT(!isPainting). So I've added the third parameter to
+ isEditablePosition to control updating the style.
+
+ Test: edition/shadow/delete-characters-in-distributed-node.html
+
+ * editing/FrameSelection.h:
+ (WebCore::FrameSelection::rendererIsEditable):
+ * editing/VisibleSelection.cpp:
+ (WebCore::VisibleSelection::rendererIsEditable):
+ (WebCore):
+ * editing/VisibleSelection.h:
+ (VisibleSelection):
+ * editing/htmlediting.cpp:
+ (WebCore::isEditablePosition):
+ * editing/htmlediting.h:
+ (WebCore):
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::paintCaret):
+
2012-06-20 Kent Tamura <[email protected]>
Unmodified form control value are overwritten by another form
Modified: trunk/Source/WebCore/editing/FrameSelection.h (120895 => 120896)
--- trunk/Source/WebCore/editing/FrameSelection.h 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/editing/FrameSelection.h 2012-06-21 01:34:11 UTC (rev 120896)
@@ -130,6 +130,7 @@
Element* rootEditableElement() const { return m_selection.rootEditableElement(); }
Element* rootEditableElementOrDocumentElement() const;
+ bool rendererIsEditable() const { return m_selection.rendererIsEditable(); }
bool isContentEditable() const { return m_selection.isContentEditable(); }
bool isContentRichlyEditable() const { return m_selection.isContentRichlyEditable(); }
Modified: trunk/Source/WebCore/editing/VisibleSelection.cpp (120895 => 120896)
--- trunk/Source/WebCore/editing/VisibleSelection.cpp 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/editing/VisibleSelection.cpp 2012-06-21 01:34:11 UTC (rev 120896)
@@ -628,6 +628,11 @@
return isEditablePosition(start());
}
+bool VisibleSelection::rendererIsEditable() const
+{
+ return isEditablePosition(start(), ContentIsEditable, DoNotUpdateStyle);
+}
+
bool VisibleSelection::isContentRichlyEditable() const
{
return isRichlyEditablePosition(start());
Modified: trunk/Source/WebCore/editing/VisibleSelection.h (120895 => 120896)
--- trunk/Source/WebCore/editing/VisibleSelection.h 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/editing/VisibleSelection.h 2012-06-21 01:34:11 UTC (rev 120896)
@@ -28,6 +28,7 @@
#include "TextGranularity.h"
#include "VisiblePosition.h"
+#include "htmlediting.h"
namespace WebCore {
@@ -99,6 +100,7 @@
Element* rootEditableElement() const;
bool isContentEditable() const;
+ bool rendererIsEditable() const;
bool isContentRichlyEditable() const;
// Returns a shadow tree node for legacy shadow trees, a child of the
// ShadowRoot node for new shadow trees, or 0 for non-shadow trees.
Modified: trunk/Source/WebCore/editing/htmlediting.cpp (120895 => 120896)
--- trunk/Source/WebCore/editing/htmlediting.cpp 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/editing/htmlediting.cpp 2012-06-21 01:34:11 UTC (rev 120896)
@@ -145,12 +145,16 @@
return lowestRoot;
}
-bool isEditablePosition(const Position& p, EditableType editableType)
+bool isEditablePosition(const Position& p, EditableType editableType, EUpdateStyle updateStyle)
{
Node* node = p.deprecatedNode();
if (!node)
return false;
-
+ if (updateStyle == UpdateStyle)
+ node->document()->updateLayoutIgnorePendingStylesheets();
+ else
+ ASSERT(updateStyle == DoNotUpdateStyle);
+
if (node->renderer() && node->renderer()->isTable())
node = node->parentNode();
Modified: trunk/Source/WebCore/editing/htmlediting.h (120895 => 120896)
--- trunk/Source/WebCore/editing/htmlediting.h 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/editing/htmlediting.h 2012-06-21 01:34:11 UTC (rev 120896)
@@ -151,8 +151,9 @@
int comparePositions(const Position&, const Position&);
// boolean functions on Position
-
-bool isEditablePosition(const Position&, EditableType = ContentIsEditable);
+
+enum EUpdateStyle { UpdateStyle, DoNotUpdateStyle };
+bool isEditablePosition(const Position&, EditableType = ContentIsEditable, EUpdateStyle = UpdateStyle);
bool isRichlyEditablePosition(const Position&, EditableType = ContentIsEditable);
bool isFirstVisiblePositionInSpecialElement(const Position&);
bool isLastVisiblePositionInSpecialElement(const Position&);
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (120895 => 120896)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-06-21 01:31:08 UTC (rev 120895)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-06-21 01:34:11 UTC (rev 120896)
@@ -2885,7 +2885,7 @@
bool isContentEditable;
if (type == CursorCaret) {
caretPainter = frame()->selection()->caretRenderer();
- isContentEditable = frame()->selection()->isContentEditable();
+ isContentEditable = frame()->selection()->rendererIsEditable();
} else {
caretPainter = frame()->page()->dragCaretController()->caretRenderer();
isContentEditable = frame()->page()->dragCaretController()->isContentEditable();