Commit 33287f11 authored by inferno@chromium.org's avatar inferno@chromium.org

Source/WebCore: Issues with merging block children of a ruby

base with another ruby base having inline children. 
https://bugs.webkit.org/show_bug.cgi?id=66124

Reviewed by Dan Bernstein.

Test: fast/ruby/ruby-base-merge-block-children-crash.html

* rendering/RenderRubyBase.cpp:
(WebCore::RenderRubyBase::moveInlineChildren): add a firstChild()
check to prevent empty anonymous block addition, just like
moveBlockChildren method.
* rendering/RenderRubyBase.cpp:
(WebCore::RenderRubyBase::moveBlockChildren): This was incorrectly
doing optimizations to see if current ruby base has only inline
children before beforeChild and then trying to take out them from 
their parent anonymous blocks. The problem is those inlines could
be split and have continuations because of encountering a block
inside inline flow. In those cases, we cannot take the inline out.
So, we should just make children non-inline in the destination
block and transfer the children as it-is.
* rendering/RenderRubyBase.h: remove unncessary functions.

LayoutTests: Issues with merging block children of a ruby
base with another ruby base having inline children.
https://bugs.webkit.org/show_bug.cgi?id=66124

Reviewed by Dan Bernstein.

* fast/ruby/ruby-base-merge-block-children-crash.html: Added.
* platform/mac/fast/ruby/ruby-base-merge-block-children-crash-expected.txt: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95924 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent eb597f44
2011-09-24 Abhishek Arya <inferno@chromium.org>
Issues with merging block children of a ruby
base with another ruby base having inline children.
https://bugs.webkit.org/show_bug.cgi?id=66124
Reviewed by Dan Bernstein.
* fast/ruby/ruby-base-merge-block-children-crash.html: Added.
* platform/mac/fast/ruby/ruby-base-merge-block-children-crash-expected.txt: Added.
2011-09-25 Philippe Normand <pnormand@igalia.com>
Unreviewed, remove fast/workers/storage/interrupt-database.html
<!DOCTYPE html>
<html style="font: 1em/1 Ahem, sans-serif;">
<body>
<ruby>
PASS
<rt id="rt1"></rt>
<i>
<table id="table1"></table><table id="table2"><span><span>
</i>
</ruby>
</body>
<script>
document.body.offsetTop;
var table1 = document.getElementById('table1');
table1.parentNode.removeChild(table1);
document.body.offsetTop;
var table2 = document.getElementById('table2');
table2.parentNode.removeChild(table2);
document.body.offsetTop;
var rt1 = document.getElementById('rt1');
rt1.parentNode.removeChild(rt1);
</script>
</body>
</html>
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x32
RenderBlock {HTML} at (0,0) size 800x32
RenderBody {BODY} at (8,8) size 784x16
RenderRuby (inline) {RUBY} at (0,0) size 64x16
RenderRubyRun (anonymous) at (0,0) size 64x16
RenderRubyBase (anonymous) at (0,0) size 64x16
RenderBlock (anonymous) at (0,0) size 64x16
RenderText {#text} at (0,0) size 64x16
text run at (0,0) width 64: "PASS"
RenderInline {I} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
RenderBlock (anonymous) at (0,16) size 64x0
RenderInline {SPAN} at (0,0) size 0x0
RenderInline {SPAN} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
RenderBlock (anonymous) at (0,16) size 64x0
RenderInline {I} at (0,0) size 0x0
2011-09-24 Abhishek Arya <inferno@chromium.org>
Issues with merging block children of a ruby
base with another ruby base having inline children.
https://bugs.webkit.org/show_bug.cgi?id=66124
Reviewed by Dan Bernstein.
Test: fast/ruby/ruby-base-merge-block-children-crash.html
* rendering/RenderRubyBase.cpp:
(WebCore::RenderRubyBase::moveInlineChildren): add a firstChild()
check to prevent empty anonymous block addition, just like
moveBlockChildren method.
* rendering/RenderRubyBase.cpp:
(WebCore::RenderRubyBase::moveBlockChildren): This was incorrectly
doing optimizations to see if current ruby base has only inline
children before beforeChild and then trying to take out them from
their parent anonymous blocks. The problem is those inlines could
be split and have continuations because of encountering a block
inside inline flow. In those cases, we cannot take the inline out.
So, we should just make children non-inline in the destination
block and transfer the children as it-is.
* rendering/RenderRubyBase.h: remove unncessary functions.
2011-09-25 Adam Barth <abarth@webkit.org>
Remove PLATFORM(HAIKU) and associated code
......@@ -53,23 +53,11 @@ bool RenderRubyBase::isChildAllowed(RenderObject* child, RenderStyle*) const
return child->isInline();
}
bool RenderRubyBase::hasOnlyWrappedInlineChildren(RenderObject* beforeChild) const
{
// Tests whether all children in the base before beforeChild are either floated/positioned,
// or inline objects wrapped in anonymous blocks.
// Note that beforeChild may be 0, in which case all children are looked at.
for (RenderObject* child = firstChild(); child != beforeChild; child = child->nextSibling()) {
if (!child->isFloatingOrPositioned() && !(child->isAnonymousBlock() && child->childrenInline()))
return false;
}
return true;
}
void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
{
// This function removes all children that are before (!) beforeChild
// and appends them to toBase.
ASSERT(toBase);
ASSERT_ARG(toBase, toBase);
// First make sure that beforeChild (if set) is indeed a direct child of this.
// Inline children might be wrapped in an anonymous block if there's a continuation.
......@@ -89,8 +77,13 @@ void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeCh
void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
{
RenderBlock* toBlock;
ASSERT(childrenInline());
ASSERT_ARG(toBase, toBase);
if (!firstChild())
return;
RenderBlock* toBlock;
if (toBase->childrenInline()) {
// The standard and easy case: move the children into the target base
toBlock = toBase;
......@@ -111,66 +104,15 @@ void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* be
void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
{
if (toBase->childrenInline()) {
// First check whether we move only wrapped inline objects.
if (hasOnlyWrappedInlineChildren(beforeChild)) {
// The reason why the base is in block flow must be after beforeChild.
// We therefore can extract the inline objects and move them to toBase.
for (RenderObject* child = firstChild(); child != beforeChild; child = firstChild()) {
if (child->isAnonymousBlock()) {
RenderBlock* anonBlock = toRenderBlock(child);
ASSERT(anonBlock->childrenInline());
ASSERT(!anonBlock->inlineElementContinuation());
anonBlock->moveAllChildrenTo(toBase, toBase->children());
anonBlock->deleteLineBoxTree();
anonBlock->destroy();
} else {
ASSERT(child->isFloatingOrPositioned());
moveChildTo(toBase, child);
}
}
} else {
// Moving block children -> have to set toBase as block flow
toBase->makeChildrenNonInline();
// Move children, potentially collapsing anonymous block wrappers.
mergeBlockChildren(toBase, beforeChild);
// Now we need to check if the leftover children are all inline.
// If so, make this base inline again.
if (hasOnlyWrappedInlineChildren()) {
RenderObject* next = 0;
for (RenderObject* child = firstChild(); child; child = next) {
next = child->nextSibling();
if (child->isFloatingOrPositioned())
continue;
ASSERT(child->isAnonymousBlock());
RenderBlock* anonBlock = toRenderBlock(child);
ASSERT(anonBlock->childrenInline());
ASSERT(!anonBlock->inlineElementContinuation());
// Move inline children out of anonymous block.
anonBlock->moveAllChildrenTo(this, anonBlock);
anonBlock->deleteLineBoxTree();
anonBlock->destroy();
}
setChildrenInline(true);
}
}
} else
mergeBlockChildren(toBase, beforeChild);
}
void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
{
// This function removes all children that are before beforeChild and appends them to toBase.
ASSERT(!childrenInline());
ASSERT(toBase);
ASSERT(!toBase->childrenInline());
ASSERT_ARG(toBase, toBase);
// Quick check whether we have anything to do, to simplify the following code.
if (!firstChild())
return;
if (toBase->childrenInline())
toBase->makeChildrenNonInline();
// If an anonymous block would be put next to another such block, then merge those.
RenderObject* firstChildHere = firstChild();
RenderObject* lastChildThere = toBase->lastChild();
......
......@@ -52,12 +52,9 @@ private:
virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
virtual void adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const;
bool hasOnlyWrappedInlineChildren(RenderObject* beforeChild = 0) const;
void moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
void moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
void moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
void mergeBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
RenderRubyRun* rubyRun() const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment