Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h |
| diff --git a/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h b/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h |
| index c8aab2a78a0c2ca7e419a96564dbcfba42361c87..1850c5e13b7f35c7c9ce8317cb7d95f02c8b3683 100644 |
| --- a/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h |
| +++ b/third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h |
| @@ -56,8 +56,8 @@ public: |
| void setToEndOfNode(Node&); |
| void childBeforeWillBeRemoved(); |
| - void invalidateOffset() const; |
| - void ensureOffsetIsValid() const; |
| + void invalidateOffset(); |
| + void markValid(); |
| DEFINE_INLINE_TRACE() |
| { |
| @@ -66,25 +66,31 @@ public: |
| } |
| private: |
| + uint64_t domTreeVersion() const; |
| + void ensureOffsetIsValid(); |
| + bool isOffsetValid() const; |
| + |
| static const int invalidOffset = -1; |
| Member<Node> m_containerNode; |
| - mutable int m_offsetInContainer; |
| Member<Node> m_childBeforeBoundary; |
| + uint64_t m_domTreeVersion; |
| + int m_offsetInContainer; |
| }; |
| inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container) |
| : m_containerNode(container) |
| - , m_offsetInContainer(0) |
| , m_childBeforeBoundary(nullptr) |
| + , m_domTreeVersion(domTreeVersion()) |
| + , m_offsetInContainer(0) |
| { |
| - DCHECK(m_containerNode); |
| } |
| inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other) |
| : m_containerNode(other.container()) |
| - , m_offsetInContainer(other.offset()) |
| , m_childBeforeBoundary(other.childBefore()) |
| + , m_domTreeVersion(other.m_domTreeVersion) |
| + , m_offsetInContainer(other.offset()) |
| { |
| } |
| @@ -98,12 +104,21 @@ inline Node* RangeBoundaryPoint::childBefore() const |
| return m_childBeforeBoundary.get(); |
| } |
| -inline void RangeBoundaryPoint::ensureOffsetIsValid() const |
| +inline uint64_t RangeBoundaryPoint::domTreeVersion() const |
| { |
| - if (m_offsetInContainer >= 0) |
| - return; |
| + return m_containerNode->document().domTreeVersion(); |
| +} |
| - DCHECK(m_childBeforeBoundary); |
| +inline void RangeBoundaryPoint::ensureOffsetIsValid() |
| +{ |
| + if (isOffsetValid()) |
| + return; |
| + DCHECK(!m_containerNode->isCharacterDataNode()); |
| + markValid(); |
| + if (!m_childBeforeBoundary) { |
| + m_offsetInContainer = 0; |
| + return; |
| + } |
| m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1; |
| } |
| @@ -112,15 +127,26 @@ inline bool RangeBoundaryPoint::inShadowIncludingDocument() const |
| return m_containerNode && m_containerNode->inShadowIncludingDocument(); |
| } |
| +inline bool RangeBoundaryPoint::isOffsetValid() const |
| +{ |
| + if (m_offsetInContainer == invalidOffset) { |
| + DCHECK(!m_containerNode->isTextNode()); |
| + return false; |
| + } |
| + return domTreeVersion() == m_domTreeVersion || m_containerNode->isCharacterDataNode(); |
| +} |
| + |
| inline const Position RangeBoundaryPoint::toPosition() const |
| { |
| - ensureOffsetIsValid(); |
| + const_cast<RangeBoundaryPoint*>(this)->ensureOffsetIsValid(); |
|
kouhei (in TOK)
2016/06/04 05:00:36
this const_cast shouldn't be needed
yosin_UTC9
2016/06/06 05:21:26
Done
|
| + // TODO(yosin): We should return |Position::beforeAnchor| when |
| + // |m_containerNode| isn't |Text| node. |
| return Position::editingPositionOf(m_containerNode.get(), m_offsetInContainer); |
| } |
| inline int RangeBoundaryPoint::offset() const |
| { |
| - ensureOffsetIsValid(); |
| + const_cast<RangeBoundaryPoint*>(this)->ensureOffsetIsValid(); |
|
kouhei (in TOK)
2016/06/04 05:00:36
ditto
yosin_UTC9
2016/06/06 05:21:26
Done
|
| return m_offsetInContainer; |
| } |
| @@ -129,6 +155,7 @@ inline void RangeBoundaryPoint::clear() |
| m_containerNode.clear(); |
| m_offsetInContainer = 0; |
| m_childBeforeBoundary = nullptr; |
| + m_domTreeVersion = 0; |
| } |
| inline void RangeBoundaryPoint::set(Node* container, int offset, Node* childBefore) |
| @@ -139,6 +166,7 @@ inline void RangeBoundaryPoint::set(Node* container, int offset, Node* childBefo |
| m_containerNode = container; |
| m_offsetInContainer = offset; |
| m_childBeforeBoundary = childBefore; |
| + markValid(); |
| } |
| inline void RangeBoundaryPoint::setOffset(int offset) |
| @@ -148,6 +176,7 @@ inline void RangeBoundaryPoint::setOffset(int offset) |
| DCHECK_GE(m_offsetInContainer, 0); |
| DCHECK(!m_childBeforeBoundary); |
| m_offsetInContainer = offset; |
| + markValid(); |
| } |
| inline void RangeBoundaryPoint::setToBeforeChild(Node& child) |
| @@ -156,6 +185,7 @@ inline void RangeBoundaryPoint::setToBeforeChild(Node& child) |
| m_childBeforeBoundary = child.previousSibling(); |
| m_containerNode = child.parentNode(); |
| m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; |
| + markValid(); |
| } |
| inline void RangeBoundaryPoint::setToStartOfNode(Node& container) |
| @@ -163,6 +193,7 @@ inline void RangeBoundaryPoint::setToStartOfNode(Node& container) |
| m_containerNode = &container; |
| m_offsetInContainer = 0; |
| m_childBeforeBoundary = nullptr; |
| + markValid(); |
| } |
| inline void RangeBoundaryPoint::setToEndOfNode(Node& container) |
| @@ -175,6 +206,7 @@ inline void RangeBoundaryPoint::setToEndOfNode(Node& container) |
| m_childBeforeBoundary = m_containerNode->lastChild(); |
| m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; |
| } |
| + markValid(); |
| } |
| inline void RangeBoundaryPoint::childBeforeWillBeRemoved() |
| @@ -185,13 +217,19 @@ inline void RangeBoundaryPoint::childBeforeWillBeRemoved() |
| m_offsetInContainer = 0; |
| else if (m_offsetInContainer > 0) |
| --m_offsetInContainer; |
| + markValid(); |
| } |
| -inline void RangeBoundaryPoint::invalidateOffset() const |
| +inline void RangeBoundaryPoint::invalidateOffset() |
| { |
| m_offsetInContainer = invalidOffset; |
| } |
| +inline void RangeBoundaryPoint::markValid() |
| +{ |
| + m_domTreeVersion = domTreeVersion(); |
| +} |
| + |
| inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b) |
| { |
| if (a.container() != b.container()) |