Changeset 259930 in webkit


Ignore:
Timestamp:
Apr 11, 2020 8:35:04 AM (4 years ago)
Author:
Darin Adler
Message:

Use Node::length to replace Node::maxCharacterOffset and lastOffsetInNode; switch more offsets from int to unsigned
https://bugs.webkit.org/show_bug.cgi?id=210246

Reviewed by Antti Koivisto.

  • The recently-added Node::length, which matches the DOM specification terminology for node offsets as used in ranges, is the same as the existing maxCharacterOffset and lastOffsetInNode functions. Deleted all uses of those and replaced them with calls to Node::length. One of the benefits of this is that Node::length is implemented more efficiently and is not a virtual function. Another is consistently matching the DOM specification terminology.
  • Many offsets, including the ones in live ranges, are currently implemented as signed in WebKit, but are specified as unsigned in the DOM and HTML specifications. This has very little observable effect from JavaScript that can affect website compatibility, but it's still helpful to be consistent both with the specification and internally. Accordingly, changed some of these to unsigned; more to come later.
  • accessibility/AXObjectCache.cpp:

(WebCore::AXObjectCache::previousBoundary): Use length instead of
maxCharacterOffset.

  • dom/CharacterData.cpp:

(WebCore::CharacterData::maxCharacterOffset const): Deleted.

  • dom/CharacterData.h: Deleted maxCharacterOffset override.
  • dom/DocumentMarkerController.cpp:

(WebCore::DocumentMarkerController::shiftMarkers): Use length instead of
maxCharacterOffset.

  • dom/Node.cpp:

(WebCore::Node::maxCharacterOffset const): Deleted.

  • dom/Node.h: Deleted maxCharacterOffset.
  • dom/Position.cpp:

(WebCore::Position::computeOffsetInContainerNode const): Use length instead
of lastOffsetInNode.

  • dom/Position.h:

(WebCore::lastOffsetInNode): Deleted.
(WebCore::lastPositionInNode): Use length instead of lastOffsetInNode.
(WebCore::minOffsetForNode): Use length instead of maxCharacterOffset.
(WebCore::offsetIsBeforeLastNodeOffset): Ditto.

  • dom/RangeBoundaryPoint.h:

(WebCore::RangeBoundaryPoint::setToEndOfNode): Use length instead of
maxCharacterOffset.

  • editing/ApplyBlockElementCommand.cpp:

(WebCore::isNewLineAtPosition): Use length instead of maxCharacterOffset.
(WebCore::ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded):
Ditto.

  • editing/ApplyStyleCommand.cpp:

(WebCore::ApplyStyleCommand::removeInlineStyle): Use length instead of
maxCharacterOffset.

  • editing/Editing.cpp:

(WebCore::lastOffsetForEditing): Use length instead of mmaxCharacterOffset
and countChildNodes. Also improved the comment here.

  • editing/EditingStyle.cpp:

(WebCore::EditingStyle::styleAtSelectionStart): Use length instead of
maxCharacterOffset.

  • editing/InsertListCommand.cpp:

(WebCore::InsertListCommand::doApplyForSingleParagraph): Use length instead
of lastOffsetInNode.

  • editing/TextIterator.cpp:

(WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
USe length instead of lastOffsetInNode.

  • editing/VisibleUnits.cpp:

(WebCore::previousBoundary): Use length instead of maxCharacterOffset.

Location:
trunk/Source/WebCore
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r259922 r259930  
     12020-04-08  Darin Adler  <darin@apple.com>
     2
     3        Use Node::length to replace Node::maxCharacterOffset and lastOffsetInNode; switch more offsets from int to unsigned
     4        https://bugs.webkit.org/show_bug.cgi?id=210246
     5
     6        Reviewed by Antti Koivisto.
     7
     8        - The recently-added Node::length, which matches the DOM specification terminology
     9          for node offsets as used in ranges, is the same as the existing maxCharacterOffset
     10          and lastOffsetInNode functions. Deleted all uses of those and replaced them
     11          with calls to Node::length. One of the benefits of this is that Node::length is
     12          implemented more efficiently and is not a virtual function. Another is consistently
     13          matching the DOM specification terminology.
     14        - Many offsets, including the ones in live ranges, are currently implemented as signed
     15          in WebKit, but are specified as unsigned in the DOM and HTML specifications. This
     16          has very little observable effect from JavaScript that can affect website compatibility,
     17          but it's still helpful to be consistent both with the specification and internally.
     18          Accordingly, changed some of these to unsigned; more to come later.
     19
     20        * accessibility/AXObjectCache.cpp:
     21        (WebCore::AXObjectCache::previousBoundary): Use length instead of
     22        maxCharacterOffset.
     23
     24        * dom/CharacterData.cpp:
     25        (WebCore::CharacterData::maxCharacterOffset const): Deleted.
     26        * dom/CharacterData.h: Deleted maxCharacterOffset override.
     27
     28        * dom/DocumentMarkerController.cpp:
     29        (WebCore::DocumentMarkerController::shiftMarkers): Use length instead of
     30        maxCharacterOffset.
     31
     32        * dom/Node.cpp:
     33        (WebCore::Node::maxCharacterOffset const): Deleted.
     34        * dom/Node.h: Deleted maxCharacterOffset.
     35
     36        * dom/Position.cpp:
     37        (WebCore::Position::computeOffsetInContainerNode const): Use length instead
     38        of lastOffsetInNode.
     39
     40        * dom/Position.h:
     41        (WebCore::lastOffsetInNode): Deleted.
     42        (WebCore::lastPositionInNode): Use length instead of lastOffsetInNode.
     43        (WebCore::minOffsetForNode): Use length instead of maxCharacterOffset.
     44        (WebCore::offsetIsBeforeLastNodeOffset): Ditto.
     45
     46        * dom/RangeBoundaryPoint.h:
     47        (WebCore::RangeBoundaryPoint::setToEndOfNode): Use length instead of
     48        maxCharacterOffset.
     49
     50        * editing/ApplyBlockElementCommand.cpp:
     51        (WebCore::isNewLineAtPosition): Use length instead of maxCharacterOffset.
     52        (WebCore::ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded):
     53        Ditto.
     54
     55        * editing/ApplyStyleCommand.cpp:
     56        (WebCore::ApplyStyleCommand::removeInlineStyle): Use length instead of
     57        maxCharacterOffset.
     58
     59        * editing/Editing.cpp:
     60        (WebCore::lastOffsetForEditing): Use length instead of mmaxCharacterOffset
     61        and countChildNodes. Also improved the comment here.
     62
     63        * editing/EditingStyle.cpp:
     64        (WebCore::EditingStyle::styleAtSelectionStart): Use length instead of
     65        maxCharacterOffset.
     66
     67        * editing/InsertListCommand.cpp:
     68        (WebCore::InsertListCommand::doApplyForSingleParagraph): Use length instead
     69        of lastOffsetInNode.
     70
     71        * editing/TextIterator.cpp:
     72        (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
     73        USe length instead of lastOffsetInNode.
     74
     75        * editing/VisibleUnits.cpp:
     76        (WebCore::previousBoundary): Use length instead of maxCharacterOffset.
     77
    1782020-04-10  Alex Christensen  <achristensen@webkit.org>
    279
  • trunk/Source/WebCore/accessibility/AXObjectCache.cpp

    r259633 r259930  
    26652665        return startOrEndCharacterOffsetForRange(rangeForNodeContents(nextSibling), false);
    26662666
    2667     if ((!suffixLength && node.isTextNode() && static_cast<int>(next) <= node.maxCharacterOffset()) || (node.renderer() && node.renderer()->isBR() && !next)) {
     2667    if ((!suffixLength && node.isTextNode() && next <= node.length()) || (node.renderer() && node.renderer()->isBR() && !next)) {
    26682668        // The next variable contains a usable index into a text node
    26692669        if (node.isTextNode())
  • trunk/Source/WebCore/accessibility/atk/WebKitAccessibleUtil.cpp

    r258871 r259930  
    169169    auto& node = *coreObject->node();
    170170    auto* lastDescendant = node.lastDescendant();
    171     unsigned lastOffset = lastOffsetInNode(lastDescendant);
     171    unsigned lastOffset = lastDescendant->length();
    172172    auto intersectsResult = range->intersectsNode(node);
    173173    return !intersectsResult.hasException()
  • trunk/Source/WebCore/dom/CharacterData.cpp

    r240237 r259930  
    240240}
    241241
    242 int CharacterData::maxCharacterOffset() const
    243 {
    244     return static_cast<int>(length());
    245 }
    246 
    247242} // namespace WebCore
  • trunk/Source/WebCore/dom/CharacterData.h

    r259575 r259930  
    6464    ExceptionOr<void> setNodeValue(const String&) final;
    6565    bool virtualIsCharacterData() const final { return true; }
    66     int maxCharacterOffset() const final;
    6766    void setDataAndUpdate(const String&, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength);
    6867    void notifyParentAfterChange(ContainerNode::ChildChangeSource);
  • trunk/Source/WebCore/dom/DocumentMarkerController.cpp

    r259575 r259930  
    598598        int targetStartOffset = marker.startOffset() + delta;
    599599        int targetEndOffset = marker.endOffset() + delta;
    600         if (targetStartOffset >= node.maxCharacterOffset() || targetEndOffset <= 0) {
     600        if (static_cast<unsigned>(targetStartOffset) >= node.length() || targetEndOffset <= 0) {
    601601            list->remove(i);
    602602            continue;
     
    616616                continue;
    617617            }
    618             marker.setEndOffset(targetEndOffset < node.maxCharacterOffset() ? targetEndOffset : node.maxCharacterOffset());
     618            marker.setEndOffset(std::min<unsigned>(targetEndOffset, node.length()));
    619619            didShiftMarker = true;
    620620        }
  • trunk/Source/WebCore/dom/Node.cpp

    r259581 r259930  
    11031103}
    11041104
    1105 int Node::maxCharacterOffset() const
    1106 {
    1107     ASSERT_NOT_REACHED();
    1108     return 0;
    1109 }
    1110 
    11111105// FIXME: Shouldn't these functions be in the editing code?  Code that asks questions about HTML in the core DOM class
    11121106// is obviously misplaced.
  • trunk/Source/WebCore/dom/Node.h

    r259575 r259930  
    378378    bool containsIncludingShadowDOM(const Node*) const;
    379379
    380     // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of
    381     // css-transform:capitalize breaking up precomposed characters and ligatures.
    382     virtual int maxCharacterOffset() const;
    383 
    384380    // Whether or not a selection can be started in this object
    385381    virtual bool canStartSelection() const;
  • trunk/Source/WebCore/dom/Position.cpp

    r258609 r259930  
    208208        return 0;
    209209    case PositionIsAfterChildren:
    210         return lastOffsetInNode(m_anchorNode.get());
     210        return m_anchorNode->length();
    211211    case PositionIsOffsetInAnchor:
    212212        return minOffsetForNode(m_anchorNode.get(), m_offset);
  • trunk/Source/WebCore/dom/Position.h

    r259184 r259930  
    2626#pragma once
    2727
     28#include "CharacterData.h"
    2829#include "ContainerNode.h"
    2930#include "EditingBoundary.h"
     
    238239Position positionAfterNode(Node* anchorNode);
    239240
    240 int lastOffsetInNode(Node*);
    241 
    242241// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to countChildNodes()
    243242Position firstPositionInNode(Node* anchorNode);
     
    307306}
    308307
    309 inline int lastOffsetInNode(Node* node)
    310 {
    311     return node->isCharacterDataNode() ? node->maxCharacterOffset() : node->countChildNodes();
    312 }
    313 
    314308// firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to countChildNodes()
    315309inline Position firstPositionInNode(Node* anchorNode)
     
    323317{
    324318    if (anchorNode->isTextNode())
    325         return Position(anchorNode, lastOffsetInNode(anchorNode), Position::PositionIsOffsetInAnchor);
     319        return Position(anchorNode, anchorNode->length(), Position::PositionIsOffsetInAnchor);
    326320    return Position(anchorNode, Position::PositionIsAfterChildren);
    327321}
     
    329323inline int minOffsetForNode(Node* anchorNode, unsigned offset)
    330324{
    331     if (anchorNode->isCharacterDataNode())
    332         return std::min<unsigned>(offset, anchorNode->maxCharacterOffset());
     325    if (is<CharacterData>(*anchorNode))
     326        return std::min(offset, downcast<CharacterData>(*anchorNode).length());
    333327
    334328    unsigned newOffset = 0;
    335329    for (Node* node = anchorNode->firstChild(); node && newOffset < offset; node = node->nextSibling())
    336330        newOffset++;
    337    
    338331    return newOffset;
    339332}
     
    341334inline bool offsetIsBeforeLastNodeOffset(unsigned offset, Node* anchorNode)
    342335{
    343     if (anchorNode->isCharacterDataNode())
    344         return offset < static_cast<unsigned>(anchorNode->maxCharacterOffset());
     336    if (is<CharacterData>(*anchorNode))
     337        return offset < downcast<CharacterData>(*anchorNode).length();
    345338
    346339    unsigned currentOffset = 0;
    347340    for (Node* node = anchorNode->firstChild(); node && currentOffset < offset; node = node->nextSibling())
    348341        currentOffset++;
    349    
    350    
    351342    return offset < currentOffset;
    352343}
  • trunk/Source/WebCore/dom/RangeBoundaryPoint.h

    r258250 r259930  
    148148{
    149149    m_containerNode = WTFMove(container);
    150     if (m_containerNode->isCharacterDataNode()) {
    151         m_offsetInContainer = m_containerNode->maxCharacterOffset();
     150    if (is<CharacterData>(*m_containerNode)) {
     151        m_offsetInContainer = downcast<CharacterData>(*m_containerNode).length();
    152152        m_childBeforeBoundary = nullptr;
    153153    } else {
  • trunk/Source/WebCore/editing/ApplyBlockElementCommand.cpp

    r259619 r259930  
    176176{
    177177    Node* textNode = position.containerNode();
    178     int offset = position.offsetInContainerNode();
    179     if (!is<Text>(textNode) || offset < 0 || offset >= textNode->maxCharacterOffset())
     178    unsigned offset = position.offsetInContainerNode();
     179    if (!is<Text>(textNode) || offset >= downcast<Text>(*textNode).length())
    180180        return false;
    181181    return downcast<Text>(*textNode).data()[offset] == '\n';
     
    233233        bool isEndAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && end.deprecatedNode() == m_endOfLastParagraph.deprecatedNode();
    234234        // Include \n at the end of line if we're at an empty paragraph
    235         if (endStyle->preserveNewline() && start == end && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) {
    236             int endOffset = end.offsetInContainerNode();
     235        unsigned endOffset = end.offsetInContainerNode();
     236        if (endStyle->preserveNewline() && start == end && endOffset < end.containerNode()->length()) {
    237237            if (!isNewLineAtPosition(end.previous()) && isNewLineAtPosition(end))
    238                 end = Position(end.containerText(), endOffset + 1);
     238                end = Position(end.containerText(), ++endOffset);
    239239            if (isEndAndEndOfLastParagraphOnSameNode && end.offsetInContainerNode() >= m_endOfLastParagraph.offsetInContainerNode())
    240240                m_endOfLastParagraph = end;
     
    242242
    243243        // If end is in the middle of a text node and the text node is editable, split.
    244         if (endStyle->userModify() != UserModify::ReadOnly && !endStyle->collapseWhiteSpace() && end.offsetInContainerNode() && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) {
     244        if (endStyle->userModify() != UserModify::ReadOnly && !endStyle->collapseWhiteSpace() && endOffset && endOffset < end.containerNode()->length()) {
    245245            RefPtr<Text> endContainer = end.containerText();
    246             splitTextNode(*endContainer, end.offsetInContainerNode());
     246            splitTextNode(*endContainer, endOffset);
    247247            if (is<Text>(endContainer) && !endContainer->previousSibling()) {
    248248                start = { };
     
    253253                start = firstPositionInOrBeforeNode(endContainer->previousSibling());
    254254            if (isEndAndEndOfLastParagraphOnSameNode) {
    255                 if (m_endOfLastParagraph.offsetInContainerNode() == end.offsetInContainerNode())
     255                if (static_cast<unsigned>(m_endOfLastParagraph.offsetInContainerNode()) == endOffset)
    256256                    m_endOfLastParagraph = lastPositionInOrAfterNode(endContainer->previousSibling());
    257257                else
    258                     m_endOfLastParagraph = Position(endContainer.get(), m_endOfLastParagraph.offsetInContainerNode() - end.offsetInContainerNode());
     258                    m_endOfLastParagraph = Position(endContainer.get(), m_endOfLastParagraph.offsetInContainerNode() - endOffset);
    259259            }
    260260            end = lastPositionInNode(endContainer->previousSibling());
  • trunk/Source/WebCore/editing/ApplyStyleCommand.cpp

    r259184 r259930  
    10921092    // e.g. if pushDownStart was at Position("hello", 5) in <b>hello<div>world</div></b>, we want Position("world", 0) instead.
    10931093    auto* pushDownStartContainer = pushDownStart.containerNode();
    1094     if (is<Text>(pushDownStartContainer) && pushDownStart.computeOffsetInContainerNode() == pushDownStartContainer->maxCharacterOffset())
     1094    if (is<Text>(pushDownStartContainer) && static_cast<unsigned>(pushDownStart.computeOffsetInContainerNode()) == downcast<Text>(*pushDownStartContainer).length())
    10951095        pushDownStart = nextVisuallyDistinctCandidate(pushDownStart);
    10961096    // If pushDownEnd is at the start of a text node, then this node is not fully selected.
  • trunk/Source/WebCore/editing/Editing.cpp

    r259575 r259930  
    378378int lastOffsetForEditing(const Node& node)
    379379{
    380     if (node.isCharacterDataNode())
    381         return node.maxCharacterOffset();
    382 
    383     if (node.hasChildNodes())
    384         return node.countChildNodes();
    385 
    386     // NOTE: This should preempt the countChildNodes() for, e.g., select nodes.
    387     // FIXME: What does the comment above mean?
    388     if (editingIgnoresContent(node))
    389         return 1;
    390 
    391     return 0;
     380    if (node.isCharacterDataNode() || node.hasChildNodes())
     381        return node.length();
     382
     383    // FIXME: Might be more helpful to return 1 for any node where editingIgnoresContent is true, even one that happens to have child nodes, like a select element with option node children.
     384    return editingIgnoresContent(node) ? 1 : 0;
    392385}
    393386
  • trunk/Source/WebCore/editing/EditingStyle.cpp

    r256580 r259930  
    14981498    // We only do this for range because caret at Position("hello", 5) in <b>hello</b>world should give you font-weight: bold.
    14991499    Node* positionNode = position.containerNode();
    1500     if (selection.isRange() && positionNode && positionNode->isTextNode() && position.computeOffsetInContainerNode() == positionNode->maxCharacterOffset())
    1501         position = nextVisuallyDistinctCandidate(position); 
     1500    if (selection.isRange() && is<Text>(positionNode) && static_cast<unsigned>(position.computeOffsetInContainerNode()) == downcast<Text>(*positionNode).length())
     1501        position = nextVisuallyDistinctCandidate(position);
    15021502
    15031503    Element* element = position.element();
  • trunk/Source/WebCore/editing/InsertListCommand.cpp

    r259899 r259930  
    257257                currentSelection->setStart(*newList, 0);
    258258            if (rangeEndIsInList && newList)
    259                 currentSelection->setEnd(*newList, lastOffsetInNode(newList.get()));
     259                currentSelection->setEnd(*newList, newList->length());
    260260
    261261            setEndingSelection(VisiblePosition(firstPositionInNode(newList.get())));
  • trunk/Source/WebCore/editing/TextIterator.cpp

    r259401 r259930  
    11351135        if (endOffset > 0 && endOffset <= endNode->countChildNodes()) {
    11361136            endNode = endNode->traverseToChildAt(endOffset - 1);
    1137             endOffset = lastOffsetInNode(endNode);
     1137            endOffset = endNode->length();
    11381138        }
    11391139    }
  • trunk/Source/WebCore/editing/VisibleUnits.cpp

    r259401 r259930  
    638638
    639639    auto& node = it.atEnd() ? searchRange->startContainer() : it.range().start.container.get();
    640     if ((!suffixLength && node.isTextNode() && static_cast<int>(next) <= node.maxCharacterOffset()) || (node.renderer() && node.renderer()->isBR() && !next)) {
     640    if ((!suffixLength && is<Text>(node) && next <= downcast<Text>(node).length()) || (node.renderer() && node.renderer()->isBR() && !next)) {
    641641        // The next variable contains a usable index into a text node
    642642        return VisiblePosition(createLegacyEditingPosition(&node, next), DOWNSTREAM);
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp

    r257839 r259930  
    469469        ASSERT(!node->firstChild());
    470470        ASSERT(node->isTextNode() || node->hasTagName(brTag));
    471         int length = node->isTextNode() ? lastOffsetInNode(node.get()) : 1;
     471        int length = is<Text>(*node) ? downcast<Text>(*node).length() : 1;
    472472
    473473        if (offset <= start && start <= offset + length)
Note: See TracChangeset for help on using the changeset viewer.