Title: [105350] branches/chromium/912
- Revision
- 105350
- Author
- infe...@chromium.org
- Date
- 2012-01-18 16:34:44 -0800 (Wed, 18 Jan 2012)
Log Message
Merge 104123 - Crash due to first-letter block processing
BUG=107277
Review URL: https://chromiumcodereview.appspot.com/9249043
Modified Paths
Added Paths
Diff
Copied: branches/chromium/912/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash-expected.txt (from rev 104123, trunk/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash-expected.txt) (0 => 105350)
--- branches/chromium/912/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash-expected.txt (rev 0)
+++ branches/chromium/912/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash-expected.txt 2012-01-19 00:34:44 UTC (rev 105350)
@@ -0,0 +1 @@
+PASS, if no exception or crash in debug
Copied: branches/chromium/912/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash.html (from rev 104123, trunk/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash.html) (0 => 105350)
--- branches/chromium/912/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash.html (rev 0)
+++ branches/chromium/912/LayoutTests/fast/css/first-letter-inline-flow-split-table-crash.html 2012-01-19 00:34:44 UTC (rev 105350)
@@ -0,0 +1,47 @@
+<style>
+.noFloat:empty { float: none; }
+.theadStyle:nth-last-child(odd) { display: table-header-group; float: right; }
+.pSpanStyle { overflow: hidden; -webkit-appearance: button; }
+.pSpanStyle:first-letter { text-align: -webkit-left; content: counter(section); }
+</style>
+<script>
+var parentSpan = document.createElement('span');
+var childSpan = document.createElement('span');
+var thead = document.createElement('thead');
+var textNode = document.createTextNode('abc');
+
+function removeTextNode() {
+ childSpan.removeChild(textNode);
+ delete textNode;
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+
+function changeClass() {
+ thead.setAttribute('class', 'noFloat');
+ setTimeout("removeTable()", 10);
+}
+
+function removeTable() {
+ childSpan.removeChild(thead);
+ setTimeout('removeTextNode();', 10);
+}
+
+function runTest() {
+ parentSpan.setAttribute('class', 'pSpanStyle');
+ document.documentElement.appendChild(parentSpan);
+ childSpan.setAttribute('class', 'noFloat');
+ parentSpan.appendChild(childSpan);
+ thead.setAttribute('class', 'theadStyle');
+ childSpan.appendChild(thead);
+ childSpan.appendChild(textNode);
+ setTimeout('changeClass();', 10);
+
+ if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+ }
+}
+window._onload_ = runTest;
+</script>
+PASS, if no exception or crash in debug
Modified: branches/chromium/912/Source/WebCore/rendering/RenderBlock.cpp (105349 => 105350)
--- branches/chromium/912/Source/WebCore/rendering/RenderBlock.cpp 2012-01-19 00:34:24 UTC (rev 105349)
+++ branches/chromium/912/Source/WebCore/rendering/RenderBlock.cpp 2012-01-19 00:34:44 UTC (rev 105350)
@@ -5616,38 +5616,14 @@
RenderTextFragment* remainingText = 0;
RenderObject* nextSibling = firstLetter->nextSibling();
- RenderObject* next = nextSibling;
- while (next) {
- if (next->isText() && toRenderText(next)->isTextFragment()) {
- remainingText = toRenderTextFragment(next);
- break;
- }
- next = next->nextSibling();
- }
- if (!remainingText && firstLetterContainer->isAnonymousBlock()) {
- // The remaining text fragment could have been wrapped in a different anonymous block since creation
- RenderObject* nextChild;
- next = firstLetterContainer->nextSibling();
- while (next && !remainingText) {
- if (next->isAnonymousBlock()) {
- nextChild = next->firstChild();
- while (nextChild) {
- if (nextChild->isText() && toRenderText(nextChild)->isTextFragment()
- && (toRenderTextFragment(nextChild)->firstLetter() == firstLetter)) {
- remainingText = toRenderTextFragment(nextChild);
- break;
- }
- nextChild = nextChild->nextSibling();
- }
- } else
- break;
- next = next->nextSibling();
- }
- }
+ RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText();
+ if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment())
+ remainingText = toRenderTextFragment(remainingTextObject);
if (remainingText) {
ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText);
// Replace the old renderer with the new one.
remainingText->setFirstLetter(newFirstLetter);
+ toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText);
}
firstLetter->destroy();
firstLetter = newFirstLetter;
@@ -5725,6 +5701,7 @@
firstLetterContainer->addChild(remainingText, textObj);
firstLetterContainer->removeChild(textObj);
remainingText->setFirstLetter(firstLetter);
+ toRenderBoxModelObject(firstLetter)->setFirstLetterRemainingText(remainingText);
// construct text fragment for the first letter
RenderTextFragment* letter =
Modified: branches/chromium/912/Source/WebCore/rendering/RenderBoxModelObject.cpp (105349 => 105350)
--- branches/chromium/912/Source/WebCore/rendering/RenderBoxModelObject.cpp 2012-01-19 00:34:24 UTC (rev 105349)
+++ branches/chromium/912/Source/WebCore/rendering/RenderBoxModelObject.cpp 2012-01-19 00:34:44 UTC (rev 105350)
@@ -64,6 +64,11 @@
typedef HashMap<const RenderBoxModelObject*, RenderBoxModelObject*> ContinuationMap;
static ContinuationMap* continuationMap = 0;
+// This HashMap is similar to the continuation map, but connects first-letter
+// renderers to their remaining text fragments.
+typedef HashMap<const RenderBoxModelObject*, RenderObject*> FirstLetterRemainingTextMap;
+static FirstLetterRemainingTextMap* firstLetterRemainingTextMap = 0;
+
class ImageQualityController {
WTF_MAKE_NONCOPYABLE(ImageQualityController); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -281,6 +286,11 @@
// A continuation of this RenderObject should be destroyed at subclasses.
ASSERT(!continuation());
+ // If this is a first-letter object with a remaining text fragment then the
+ // entry needs to be cleared from the map.
+ if (firstLetterRemainingText())
+ setFirstLetterRemainingText(0);
+
// RenderObject::willBeDestroyed calls back to destroyLayer() for layer destruction
RenderObject::willBeDestroyed();
}
@@ -2573,6 +2583,23 @@
}
}
+RenderObject* RenderBoxModelObject::firstLetterRemainingText() const
+{
+ if (!firstLetterRemainingTextMap)
+ return 0;
+ return firstLetterRemainingTextMap->get(this);
+}
+
+void RenderBoxModelObject::setFirstLetterRemainingText(RenderObject* remainingText)
+{
+ if (remainingText) {
+ if (!firstLetterRemainingTextMap)
+ firstLetterRemainingTextMap = new FirstLetterRemainingTextMap;
+ firstLetterRemainingTextMap->set(this, remainingText);
+ } else if (firstLetterRemainingTextMap)
+ firstLetterRemainingTextMap->remove(this);
+}
+
bool RenderBoxModelObject::shouldAntialiasLines(GraphicsContext* context)
{
// FIXME: We may want to not antialias when scaled by an integral value,
Modified: branches/chromium/912/Source/WebCore/rendering/RenderBoxModelObject.h (105349 => 105350)
--- branches/chromium/912/Source/WebCore/rendering/RenderBoxModelObject.h 2012-01-19 00:34:24 UTC (rev 105349)
+++ branches/chromium/912/Source/WebCore/rendering/RenderBoxModelObject.h 2012-01-19 00:34:44 UTC (rev 105350)
@@ -192,6 +192,11 @@
static bool shouldAntialiasLines(GraphicsContext*);
+public:
+ // For RenderBlocks and RenderInlines with m_style->styleType() == FIRST_LETTER, this tracks their remaining text fragments
+ RenderObject* firstLetterRemainingText() const;
+ void setFirstLetterRemainingText(RenderObject*);
+
private:
virtual bool isBoxModelObject() const { return true; }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes