Changeset 58665 in webkit


Ignore:
Timestamp:
May 2, 2010 9:25:27 PM (14 years ago)
Author:
mitz@apple.com
Message:

Another case of <rdar://problem/7552959> REGRESSION: Infinite recursion in Position::getInlineBoxAndOffset()
https://bugs.webkit.org/show_bug.cgi?id=38445

Reviewed by Simon Fraser.

WebCore:

Test: editing/selection/mixed-editability-11.html

  • dom/Position.cpp:

(WebCore::downstreamIgnoringEditingBoundaries): Added. Returns the furthest visually equivalent
position downstream, crossing any editability boundaries.
(WebCore::upstreamIgnoringEditingBoundaries): Similarly for upstream.
(WebCore::Position::getInlineBoxAndOffset): Changed the logic for finding an inline box for positions
whose node is a block flow. Instead of traversing the DOM, advance downstream or upstream as far as
possible, crossing any editability boudaries. Infinite recursion is avoided by advancing all the way
and checking that the new position is different from the starting position. Also replaced the specific
test for buttons with the generic and more comprehensive canHaveChildrenForEditing().

LayoutTests:

  • editing/selection/mixed-editability-11-expected.txt: Added.
  • editing/selection/mixed-editability-11.html: Added.
Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r58656 r58665  
     12010-05-02  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        Another case of <rdar://problem/7552959> REGRESSION: Infinite recursion in Position::getInlineBoxAndOffset()
     6        https://bugs.webkit.org/show_bug.cgi?id=38445
     7
     8        * editing/selection/mixed-editability-11-expected.txt: Added.
     9        * editing/selection/mixed-editability-11.html: Added.
     10
    1112010-05-02  Dirk Schulze  <krit@webkit.org>
    212
  • trunk/WebCore/ChangeLog

    r58662 r58665  
     12010-05-02  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        Another case of <rdar://problem/7552959> REGRESSION: Infinite recursion in Position::getInlineBoxAndOffset()
     6        https://bugs.webkit.org/show_bug.cgi?id=38445
     7
     8        Test: editing/selection/mixed-editability-11.html
     9
     10        * dom/Position.cpp:
     11        (WebCore::downstreamIgnoringEditingBoundaries): Added. Returns the furthest visually equivalent
     12        position downstream, crossing any editability boundaries.
     13        (WebCore::upstreamIgnoringEditingBoundaries): Similarly for upstream.
     14        (WebCore::Position::getInlineBoxAndOffset): Changed the logic for finding an inline box for positions
     15        whose node is a block flow. Instead of traversing the DOM, advance downstream or upstream as far as
     16        possible, crossing any editability boudaries. Infinite recursion is avoided by advancing all the way
     17        and checking that the new position is different from the starting position. Also replaced the specific
     18        test for buttons with the generic and more comprehensive canHaveChildrenForEditing().
     19
    1202010-05-02  Tasuku Suzuki  <tasuku.suzuki@nokia.com>
    221
  • trunk/WebCore/dom/Position.cpp

    r57110 r58665  
    987987}
    988988
     989static Position downstreamIgnoringEditingBoundaries(Position position)
     990{
     991    Position lastPosition;
     992    while (position != lastPosition) {
     993        lastPosition = position;
     994        position = position.downstream(Position::CanCrossEditingBoundary);
     995    }
     996    return position;
     997}
     998
     999static Position upstreamIgnoringEditingBoundaries(Position position)
     1000{
     1001    Position lastPosition;
     1002    while (position != lastPosition) {
     1003        lastPosition = position;
     1004        position = position.upstream(Position::CanCrossEditingBoundary);
     1005    }
     1006    return position;
     1007}
     1008
    9891009void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
    9901010{
    9911011    caretOffset = m_offset;
    9921012    RenderObject* renderer = node()->renderer();
    993          
     1013
    9941014    if (!renderer->isText()) {
    995         if (!renderer->isRenderButton() && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
    996             bool lastPosition = caretOffset == lastOffsetInNode(node());
    997             Node* startNode = lastPosition ? node()->childNode(caretOffset - 1) : node()->childNode(caretOffset);
    998             while (startNode && (!startNode->renderer() || (startNode->isTextNode() && toRenderText(startNode->renderer())->isAllCollapsibleWhitespace())))
    999                 startNode = (lastPosition)? startNode->previousSibling(): startNode->nextSibling();
    1000             if (startNode) {
    1001                 Position pos(startNode, 0);
    1002                 pos = pos.downstream(CanCrossEditingBoundary);
    1003                 pos.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
    1004                 if (lastPosition && inlineBox)
    1005                     caretOffset = inlineBox->caretMaxOffset();
     1015        inlineBox = 0;
     1016        if (canHaveChildrenForEditing(node()) && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) {
     1017            // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in
     1018            // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning
     1019            // of RenderObject::createVisiblePosition().
     1020            Position equivalent = downstreamIgnoringEditingBoundaries(*this);
     1021            if (equivalent == *this)
     1022                equivalent = upstreamIgnoringEditingBoundaries(*this);
     1023            if (equivalent == *this)
    10061024                return;
    1007             }
    1008         }
    1009         inlineBox = 0;
     1025
     1026            equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset);
     1027            return;
     1028        }
    10101029        if (renderer->isBox()) {
    10111030            inlineBox = toRenderBox(renderer)->inlineBoxWrapper();
Note: See TracChangeset for help on using the changeset viewer.