Changeset 163825 in webkit


Ignore:
Timestamp:
Feb 10, 2014 3:05:19 PM (10 years ago)
Author:
rniwa@webkit.org
Message:

HTMLTextFormControlElement::setSelectionRange shouldn't use VisiblePosition
https://bugs.webkit.org/show_bug.cgi?id=128478

Reviewed by Darin Adler.

Added positionForIndex to compute Position given a selection index. This function doesn't
synchronously trigger like visiblePositionForIndex.

Also added assertions in visiblePositionForIndex and visiblePositionForIndex to make sure
they are inverse of one another.

  • html/HTMLTextFormControlElement.cpp:

(WebCore::HTMLTextFormControlElement::setSelectionRange): Use positionForIndex. Also removed
the now tautological assertions since we would never create a position outside the inner text
element.

(WebCore::HTMLTextFormControlElement::indexForVisiblePosition): Fixed the bug where this
function could return a selection index beyond innerTextElement in some types of input
elements such as search fields. fast/forms/search-disabled-readonly.html hits the newly
added assertion without this change. Note we can't use visiblePositionForIndex here as that
would result in a mutual recursion with the assertion in visiblePositionForIndex.

(WebCore::HTMLTextFormControlElement::visiblePositionForIndex): Added an assertion.

(WebCore::positionForIndex): Added. It's here with prototype at the beginning of the file
so that it's right next to HTMLTextFormControlElement::innerText() where we do a similar
DOM traversal to obtain the inner text value.

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r163823 r163825  
     12014-02-10  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        HTMLTextFormControlElement::setSelectionRange shouldn't use VisiblePosition
     4        https://bugs.webkit.org/show_bug.cgi?id=128478
     5
     6        Reviewed by Darin Adler.
     7
     8        Added positionForIndex to compute Position given a selection index. This function doesn't
     9        synchronously trigger like visiblePositionForIndex.
     10
     11        Also added assertions in visiblePositionForIndex and visiblePositionForIndex to make sure
     12        they are inverse of one another.
     13
     14        * html/HTMLTextFormControlElement.cpp:
     15        (WebCore::HTMLTextFormControlElement::setSelectionRange): Use positionForIndex. Also removed
     16        the now tautological assertions since we would never create a position outside the inner text
     17        element.
     18
     19        (WebCore::HTMLTextFormControlElement::indexForVisiblePosition): Fixed the bug where this
     20        function could return a selection index beyond innerTextElement in some types of input
     21        elements such as search fields. fast/forms/search-disabled-readonly.html hits the newly
     22        added assertion without this change. Note we can't use visiblePositionForIndex here as that
     23        would result in a mutual recursion with the assertion in visiblePositionForIndex.
     24
     25        (WebCore::HTMLTextFormControlElement::visiblePositionForIndex): Added an assertion.
     26
     27        (WebCore::positionForIndex): Added. It's here with prototype at the beginning of the file
     28        so that it's right next to HTMLTextFormControlElement::innerText() where we do a similar
     29        DOM traversal to obtain the inner text value.
     30
    1312014-02-07  Jeffrey Pfau  <jpfau@apple.com>
    232
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp

    r163721 r163825  
    5353using namespace HTMLNames;
    5454
     55static Position positionForIndex(TextControlInnerTextElement*, unsigned);
     56
    5557HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
    5658    : HTMLFormControlElementWithState(tagName, document, form)
     
    297299    start = std::min(std::max(start, 0), end);
    298300
    299     if (!hasVisibleTextArea(*renderer(), innerTextElement())) {
     301    TextControlInnerTextElement* innerText = innerTextElement();
     302    if (!hasVisibleTextArea(*renderer(), innerText)) {
    300303        cacheSelection(start, end, direction);
    301304        return;
    302305    }
    303     VisiblePosition startPosition = visiblePositionForIndex(start);
    304     VisiblePosition endPosition;
     306    Position startPosition = positionForIndex(innerText, start);
     307    Position endPosition;
    305308    if (start == end)
    306309        endPosition = startPosition;
    307310    else
    308         endPosition = visiblePositionForIndex(end);
    309 
    310 #if !PLATFORM(IOS)
    311     // startPosition and endPosition can be null position for example when
    312     // "-webkit-user-select: none" style attribute is specified.
    313     if (startPosition.isNotNull() && endPosition.isNotNull()) {
    314         ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this
    315             && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == this);
    316     }
    317 #endif
     311        endPosition = positionForIndex(innerText, end);
     312
    318313    VisibleSelection newSelection;
    319314    if (direction == SelectionHasBackwardDirection)
     
    329324int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
    330325{
    331     if (enclosingTextFormControl(pos.deepEquivalent()) != this)
     326    TextControlInnerTextElement* innerText = innerTextElement();
     327    if (!innerText || !innerText->contains(pos.deepEquivalent().anchorNode()))
    332328        return 0;
    333329    bool forSelectionPreservation = false;
    334     return WebCore::indexForVisiblePosition(innerTextElement(), pos, forSelectionPreservation);
     330    unsigned index = WebCore::indexForVisiblePosition(innerTextElement(), pos, forSelectionPreservation);
     331    ASSERT(VisiblePosition(positionForIndex(innerTextElement(), index)) == pos);
     332    return index;
    335333}
    336334
    337335VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
    338336{
    339     return visiblePositionForIndexUsingCharacterIterator(innerTextElement(), index);
     337    VisiblePosition position = positionForIndex(innerTextElement(), index);
     338    ASSERT(indexForVisiblePosition(position) == index);
     339    return position;
    340340}
    341341
     
    556556    }
    557557    return finishText(result);
     558}
     559
     560static Position positionForIndex(TextControlInnerTextElement* innerText, unsigned index)
     561{
     562    unsigned remainingCharactersToMoveForward = index;
     563    for (Node* node = innerText; node; node = NodeTraversal::next(node, innerText)) {
     564        if (node->hasTagName(brTag)) {
     565            if (!remainingCharactersToMoveForward)
     566                return positionBeforeNode(node);
     567            remainingCharactersToMoveForward--;
     568        } else if (node->isTextNode()) {
     569            Text* text = toText(node);
     570            if (remainingCharactersToMoveForward < text->length())
     571                return Position(text, remainingCharactersToMoveForward);
     572            remainingCharactersToMoveForward -= text->length();
     573        }
     574    }
     575    return lastPositionInNode(innerText);
    558576}
    559577
Note: See TracChangeset for help on using the changeset viewer.