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..401a563078cd906d230b6eb010c7f4819295cefc 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() const; |
DEFINE_INLINE_TRACE() |
{ |
@@ -66,25 +66,31 @@ public: |
} |
private: |
+ uint64_t domTreeVersion() const; |
+ void ensureOffsetIsValid() const; |
+ bool isOffsetValid() const; |
+ |
static const int invalidOffset = -1; |
Member<Node> m_containerNode; |
- mutable int m_offsetInContainer; |
Member<Node> m_childBeforeBoundary; |
+ mutable uint64_t m_domTreeVersion; |
+ mutable 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 uint64_t RangeBoundaryPoint::domTreeVersion() const |
+{ |
+ return m_containerNode->document().domTreeVersion(); |
+} |
+ |
inline void RangeBoundaryPoint::ensureOffsetIsValid() const |
{ |
- if (m_offsetInContainer >= 0) |
+ if (isOffsetValid()) |
return; |
- |
- DCHECK(m_childBeforeBoundary); |
+ DCHECK(!m_containerNode->isCharacterDataNode()); |
+ markValid(); |
+ if (!m_childBeforeBoundary) { |
+ m_offsetInContainer = 0; |
+ return; |
+ } |
m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1; |
} |
@@ -112,9 +127,20 @@ 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(); |
+ // TODO(yosin): We should return |Position::beforeAnchor| when |
+ // |m_containerNode| isn't |Text| node. |
return Position::editingPositionOf(m_containerNode.get(), 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() const |
+{ |
+ m_domTreeVersion = domTreeVersion(); |
+} |
+ |
inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b) |
{ |
if (a.container() != b.container()) |