Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: third_party/WebKit/Source/core/dom/RangeBoundaryPoint.h

Issue 2034023003: Make appendChild/insertBefore faster with active ranges (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 2016-06-06T14:17:03 Adopt for review comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/dom/Range.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 void clear(); 49 void clear();
50 50
51 void set(Node* container, int offset, Node* childBefore); 51 void set(Node* container, int offset, Node* childBefore);
52 void setOffset(int); 52 void setOffset(int);
53 53
54 void setToBeforeChild(Node&); 54 void setToBeforeChild(Node&);
55 void setToStartOfNode(Node&); 55 void setToStartOfNode(Node&);
56 void setToEndOfNode(Node&); 56 void setToEndOfNode(Node&);
57 57
58 void childBeforeWillBeRemoved(); 58 void childBeforeWillBeRemoved();
59 void invalidateOffset() const; 59 void invalidateOffset();
60 void ensureOffsetIsValid() const; 60 void markValid() const;
61 61
62 DEFINE_INLINE_TRACE() 62 DEFINE_INLINE_TRACE()
63 { 63 {
64 visitor->trace(m_containerNode); 64 visitor->trace(m_containerNode);
65 visitor->trace(m_childBeforeBoundary); 65 visitor->trace(m_childBeforeBoundary);
66 } 66 }
67 67
68 private: 68 private:
69 uint64_t domTreeVersion() const;
70 void ensureOffsetIsValid() const;
71 bool isOffsetValid() const;
72
69 static const int invalidOffset = -1; 73 static const int invalidOffset = -1;
70 74
71 Member<Node> m_containerNode; 75 Member<Node> m_containerNode;
76 Member<Node> m_childBeforeBoundary;
77 mutable uint64_t m_domTreeVersion;
72 mutable int m_offsetInContainer; 78 mutable int m_offsetInContainer;
73 Member<Node> m_childBeforeBoundary;
74 }; 79 };
75 80
76 inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container) 81 inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container)
77 : m_containerNode(container) 82 : m_containerNode(container)
83 , m_childBeforeBoundary(nullptr)
84 , m_domTreeVersion(domTreeVersion())
78 , m_offsetInContainer(0) 85 , m_offsetInContainer(0)
79 , m_childBeforeBoundary(nullptr)
80 { 86 {
81 DCHECK(m_containerNode);
82 } 87 }
83 88
84 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other) 89 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
85 : m_containerNode(other.container()) 90 : m_containerNode(other.container())
91 , m_childBeforeBoundary(other.childBefore())
92 , m_domTreeVersion(other.m_domTreeVersion)
86 , m_offsetInContainer(other.offset()) 93 , m_offsetInContainer(other.offset())
87 , m_childBeforeBoundary(other.childBefore())
88 { 94 {
89 } 95 }
90 96
91 inline Node* RangeBoundaryPoint::container() const 97 inline Node* RangeBoundaryPoint::container() const
92 { 98 {
93 return m_containerNode.get(); 99 return m_containerNode.get();
94 } 100 }
95 101
96 inline Node* RangeBoundaryPoint::childBefore() const 102 inline Node* RangeBoundaryPoint::childBefore() const
97 { 103 {
98 return m_childBeforeBoundary.get(); 104 return m_childBeforeBoundary.get();
99 } 105 }
100 106
107 inline uint64_t RangeBoundaryPoint::domTreeVersion() const
108 {
109 return m_containerNode->document().domTreeVersion();
110 }
111
101 inline void RangeBoundaryPoint::ensureOffsetIsValid() const 112 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
102 { 113 {
103 if (m_offsetInContainer >= 0) 114 if (isOffsetValid())
104 return; 115 return;
105 116 DCHECK(!m_containerNode->isCharacterDataNode());
106 DCHECK(m_childBeforeBoundary); 117 markValid();
118 if (!m_childBeforeBoundary) {
119 m_offsetInContainer = 0;
120 return;
121 }
107 m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1; 122 m_offsetInContainer = m_childBeforeBoundary->nodeIndex() + 1;
108 } 123 }
109 124
110 inline bool RangeBoundaryPoint::inShadowIncludingDocument() const 125 inline bool RangeBoundaryPoint::inShadowIncludingDocument() const
111 { 126 {
112 return m_containerNode && m_containerNode->inShadowIncludingDocument(); 127 return m_containerNode && m_containerNode->inShadowIncludingDocument();
113 } 128 }
114 129
130 inline bool RangeBoundaryPoint::isOffsetValid() const
131 {
132 if (m_offsetInContainer == invalidOffset) {
133 DCHECK(!m_containerNode->isTextNode());
134 return false;
135 }
136 return domTreeVersion() == m_domTreeVersion || m_containerNode->isCharacterD ataNode();
137 }
138
115 inline const Position RangeBoundaryPoint::toPosition() const 139 inline const Position RangeBoundaryPoint::toPosition() const
116 { 140 {
117 ensureOffsetIsValid(); 141 ensureOffsetIsValid();
142 // TODO(yosin): We should return |Position::beforeAnchor| when
143 // |m_containerNode| isn't |Text| node.
118 return Position::editingPositionOf(m_containerNode.get(), m_offsetInContaine r); 144 return Position::editingPositionOf(m_containerNode.get(), m_offsetInContaine r);
119 } 145 }
120 146
121 inline int RangeBoundaryPoint::offset() const 147 inline int RangeBoundaryPoint::offset() const
122 { 148 {
123 ensureOffsetIsValid(); 149 ensureOffsetIsValid();
124 return m_offsetInContainer; 150 return m_offsetInContainer;
125 } 151 }
126 152
127 inline void RangeBoundaryPoint::clear() 153 inline void RangeBoundaryPoint::clear()
128 { 154 {
129 m_containerNode.clear(); 155 m_containerNode.clear();
130 m_offsetInContainer = 0; 156 m_offsetInContainer = 0;
131 m_childBeforeBoundary = nullptr; 157 m_childBeforeBoundary = nullptr;
158 m_domTreeVersion = 0;
132 } 159 }
133 160
134 inline void RangeBoundaryPoint::set(Node* container, int offset, Node* childBefo re) 161 inline void RangeBoundaryPoint::set(Node* container, int offset, Node* childBefo re)
135 { 162 {
136 DCHECK(container); 163 DCHECK(container);
137 DCHECK_GE(offset, 0); 164 DCHECK_GE(offset, 0);
138 DCHECK_EQ(childBefore, offset ? NodeTraversal::childAt(*container, offset - 1) : 0); 165 DCHECK_EQ(childBefore, offset ? NodeTraversal::childAt(*container, offset - 1) : 0);
139 m_containerNode = container; 166 m_containerNode = container;
140 m_offsetInContainer = offset; 167 m_offsetInContainer = offset;
141 m_childBeforeBoundary = childBefore; 168 m_childBeforeBoundary = childBefore;
169 markValid();
142 } 170 }
143 171
144 inline void RangeBoundaryPoint::setOffset(int offset) 172 inline void RangeBoundaryPoint::setOffset(int offset)
145 { 173 {
146 DCHECK(m_containerNode); 174 DCHECK(m_containerNode);
147 DCHECK(m_containerNode->offsetInCharacters()); 175 DCHECK(m_containerNode->offsetInCharacters());
148 DCHECK_GE(m_offsetInContainer, 0); 176 DCHECK_GE(m_offsetInContainer, 0);
149 DCHECK(!m_childBeforeBoundary); 177 DCHECK(!m_childBeforeBoundary);
150 m_offsetInContainer = offset; 178 m_offsetInContainer = offset;
179 markValid();
151 } 180 }
152 181
153 inline void RangeBoundaryPoint::setToBeforeChild(Node& child) 182 inline void RangeBoundaryPoint::setToBeforeChild(Node& child)
154 { 183 {
155 DCHECK(child.parentNode()); 184 DCHECK(child.parentNode());
156 m_childBeforeBoundary = child.previousSibling(); 185 m_childBeforeBoundary = child.previousSibling();
157 m_containerNode = child.parentNode(); 186 m_containerNode = child.parentNode();
158 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; 187 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
188 markValid();
159 } 189 }
160 190
161 inline void RangeBoundaryPoint::setToStartOfNode(Node& container) 191 inline void RangeBoundaryPoint::setToStartOfNode(Node& container)
162 { 192 {
163 m_containerNode = &container; 193 m_containerNode = &container;
164 m_offsetInContainer = 0; 194 m_offsetInContainer = 0;
165 m_childBeforeBoundary = nullptr; 195 m_childBeforeBoundary = nullptr;
196 markValid();
166 } 197 }
167 198
168 inline void RangeBoundaryPoint::setToEndOfNode(Node& container) 199 inline void RangeBoundaryPoint::setToEndOfNode(Node& container)
169 { 200 {
170 m_containerNode = &container; 201 m_containerNode = &container;
171 if (m_containerNode->offsetInCharacters()) { 202 if (m_containerNode->offsetInCharacters()) {
172 m_offsetInContainer = m_containerNode->maxCharacterOffset(); 203 m_offsetInContainer = m_containerNode->maxCharacterOffset();
173 m_childBeforeBoundary = nullptr; 204 m_childBeforeBoundary = nullptr;
174 } else { 205 } else {
175 m_childBeforeBoundary = m_containerNode->lastChild(); 206 m_childBeforeBoundary = m_containerNode->lastChild();
176 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0; 207 m_offsetInContainer = m_childBeforeBoundary ? invalidOffset : 0;
177 } 208 }
209 markValid();
178 } 210 }
179 211
180 inline void RangeBoundaryPoint::childBeforeWillBeRemoved() 212 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
181 { 213 {
182 DCHECK(m_offsetInContainer); 214 DCHECK(m_offsetInContainer);
183 m_childBeforeBoundary = m_childBeforeBoundary->previousSibling(); 215 m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
184 if (!m_childBeforeBoundary) 216 if (!m_childBeforeBoundary)
185 m_offsetInContainer = 0; 217 m_offsetInContainer = 0;
186 else if (m_offsetInContainer > 0) 218 else if (m_offsetInContainer > 0)
187 --m_offsetInContainer; 219 --m_offsetInContainer;
220 markValid();
188 } 221 }
189 222
190 inline void RangeBoundaryPoint::invalidateOffset() const 223 inline void RangeBoundaryPoint::invalidateOffset()
191 { 224 {
192 m_offsetInContainer = invalidOffset; 225 m_offsetInContainer = invalidOffset;
193 } 226 }
194 227
228 inline void RangeBoundaryPoint::markValid() const
229 {
230 m_domTreeVersion = domTreeVersion();
231 }
232
195 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b) 233 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
196 { 234 {
197 if (a.container() != b.container()) 235 if (a.container() != b.container())
198 return false; 236 return false;
199 if (a.childBefore() || b.childBefore()) { 237 if (a.childBefore() || b.childBefore()) {
200 if (a.childBefore() != b.childBefore()) 238 if (a.childBefore() != b.childBefore())
201 return false; 239 return false;
202 } else { 240 } else {
203 if (a.offset() != b.offset()) 241 if (a.offset() != b.offset())
204 return false; 242 return false;
205 } 243 }
206 return true; 244 return true;
207 } 245 }
208 246
209 } // namespace blink 247 } // namespace blink
210 248
211 #endif 249 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/Range.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698