| Index: third_party/WebKit/Source/core/editing/DOMSelection.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
|
| index da74aa29d601e9082424cc260e49acffe948b5b7..8d1a24704a2080ce07acdbb13d972dded6a10509 100644
|
| --- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
|
| @@ -81,6 +81,13 @@ bool DOMSelection::isBaseFirstInSelection() const {
|
| return selection.base() <= selection.extent();
|
| }
|
|
|
| +const Position& DOMSelection::anchorPosition() const {
|
| + DCHECK(frame());
|
| + return frame()->selection().selectionInDOMTree().base();
|
| +}
|
| +
|
| +// TODO(tkent): Following four functions based on VisibleSelection should be
|
| +// removed.
|
| static Position anchorPosition(const VisibleSelection& selection) {
|
| Position anchor =
|
| selection.isBaseFirst() ? selection.start() : selection.end();
|
| @@ -405,7 +412,10 @@ void DOMSelection::extend(Node* node,
|
| int offset,
|
| ExceptionState& exceptionState) {
|
| DCHECK(node);
|
| + // https://www.w3.org/TR/selection-api/#dom-selection-extend
|
|
|
| + // 2. If the context object is empty, throw an InvalidStateError exception and
|
| + // abort these steps.
|
| if (rangeCount() == 0) {
|
| exceptionState.throwDOMException(
|
| InvalidStateError, "This Selection object doesn't have any Ranges.");
|
| @@ -421,25 +431,51 @@ void DOMSelection::extend(Node* node,
|
| if (exceptionState.hadException())
|
| return;
|
|
|
| + // 1. If node's root is not the document associated with the context object,
|
| + // abort these steps.
|
| if (!isValidForPosition(node))
|
| return;
|
|
|
| + // 3. Let oldAnchor and oldFocus be the context object's anchor and focus, and
|
| + // let newFocus be the boundary point (node, offset).
|
| + const Position& oldAnchor = anchorPosition();
|
| + DCHECK(!oldAnchor.isNull());
|
| + const Position newFocus(node, offset);
|
| +
|
| clearCachedRangeIfSelectionOfDocument();
|
| - const Position& base = frame()->selection().base();
|
| - if (base.isNull()) {
|
| - // TODO(editing-dev): We should throw |InvalidStateError| if selection is
|
| - // none to follow the spec.
|
| - frame()->selection().setSelection(SelectionInDOMTree::Builder()
|
| - .collapse(Position(node, offset))
|
| - .setIsDirectional(true)
|
| - .build());
|
| - return;
|
| +
|
| + // 4. Let newRange be a new range.
|
| + Range* newRange = Range::create(*frame()->document());
|
| +
|
| + // 5. If node's root is not the same as the context object's range's root, set
|
| + // newRange's start and end to newFocus.
|
| + // E.g. oldAnchor might point in shadow Text node in TextControlElement.
|
| + if (oldAnchor.anchorNode()->treeRoot() != node->treeRoot()) {
|
| + newRange->setStart(node, offset);
|
| + newRange->setEnd(node, offset);
|
| +
|
| + } else if (oldAnchor <= newFocus) {
|
| + // 6. Otherwise, if oldAnchor is before or equal to newFocus, set newRange's
|
| + // start to oldAnchor, then set its end to newFocus.
|
| + newRange->setStart(oldAnchor.anchorNode(),
|
| + oldAnchor.offsetInContainerNode());
|
| + newRange->setEnd(node, offset);
|
| +
|
| + } else {
|
| + // 7. Otherwise, set newRange's start to newFocus, then set its end to
|
| + // oldAnchor.
|
| + newRange->setStart(node, offset);
|
| + newRange->setEnd(oldAnchor.anchorNode(), oldAnchor.offsetInContainerNode());
|
| }
|
| - frame()->selection().setSelection(SelectionInDOMTree::Builder()
|
| - .collapse(base)
|
| - .extend(Position(node, offset))
|
| - .setIsDirectional(true)
|
| - .build());
|
| +
|
| + // 8. Set the context object's range to newRange.
|
| + SelectionInDOMTree::Builder builder;
|
| + if (newRange->collapsed())
|
| + builder.collapse(newFocus);
|
| + else
|
| + builder.collapse(oldAnchor).extend(newFocus);
|
| + frame()->selection().setSelection(builder.setIsDirectional(true).build());
|
| + cacheRangeIfSelectionOfDocument(newRange);
|
| }
|
|
|
| Range* DOMSelection::getRangeAt(int index,
|
| @@ -469,7 +505,7 @@ Range* DOMSelection::primaryRangeOrNull() const {
|
| }
|
|
|
| Range* DOMSelection::createRangeFromSelectionEditor() const {
|
| - Position anchor = anchorPosition(visibleSelection());
|
| + Position anchor = blink::anchorPosition(visibleSelection());
|
| if (isSelectionOfDocument() && !anchor.anchorNode()->isInShadowTree())
|
| return frame()->selection().firstRange();
|
|
|
|
|