https://bugs.webkit.org/show_bug.cgi?id=145686
Reviewed by Enrica Casucci.
The bug was caused by nextCandidate and nextVisuallyDistinctCandidate traversing through each character
in a text node without a renderer. Skip any node that doesn't have a renderer in both of those functions
and corresponding previous* functions.
It's fine to skip unrendered nodes in PositionIterator because only other clients of PositionIterator
are Position::upstream and Position::downstream and they don't care about un-rendered nodes either.
* dom/PositionIterator.cpp:
(WebCore::PositionIterator::increment):
(WebCore::PositionIterator::decrement):
* editing/htmlediting.cpp:
(WebCore::nextVisuallyDistinctCandidate):
(WebCore::previousVisuallyDistinctCandidate):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@185287
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-06-06 Ryosuke Niwa <rniwa@webkit.org>
+
+ Typing is slow in Gmail on iPads
+ https://bugs.webkit.org/show_bug.cgi?id=145686
+
+ Reviewed by Enrica Casucci.
+
+ The bug was caused by nextCandidate and nextVisuallyDistinctCandidate traversing through each character
+ in a text node without a renderer. Skip any node that doesn't have a renderer in both of those functions
+ and corresponding previous* functions.
+
+ It's fine to skip unrendered nodes in PositionIterator because only other clients of PositionIterator
+ are Position::upstream and Position::downstream and they don't care about un-rendered nodes either.
+
+ * dom/PositionIterator.cpp:
+ (WebCore::PositionIterator::increment):
+ (WebCore::PositionIterator::decrement):
+ * editing/htmlediting.cpp:
+ (WebCore::nextVisuallyDistinctCandidate):
+ (WebCore::previousVisuallyDistinctCandidate):
+
2015-06-06 Mark Lam <mark.lam@apple.com>
Returned Exception* values need to be initialized to nullptr when no exceptions are thrown.
return;
}
- if (!m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
+ if (m_anchorNode->renderer() && !m_anchorNode->hasChildNodes() && m_offsetInAnchor < lastOffsetForEditing(m_anchorNode))
m_offsetInAnchor = Position::uncheckedNextOffset(m_anchorNode, m_offsetInAnchor);
else {
m_nodeAfterPositionInAnchor = m_anchorNode;
m_anchorNode = m_anchorNode->lastChild();
m_offsetInAnchor = m_anchorNode->hasChildNodes()? 0: lastOffsetForEditing(m_anchorNode);
} else {
- if (m_offsetInAnchor)
+ if (m_offsetInAnchor && m_anchorNode->renderer())
m_offsetInAnchor = Position::uncheckedPreviousOffset(m_anchorNode, m_offsetInAnchor);
else {
m_nodeAfterPositionInAnchor = m_anchorNode;
Position nextVisuallyDistinctCandidate(const Position& position)
{
+ // FIXME: Use PositionIterator instead.
Position p = position;
Position downstreamStart = p.downstream();
while (!p.atEndOfTree()) {
p = p.next(Character);
if (p.isCandidate() && p.downstream() != downstreamStart)
return p;
+ if (auto* node = p.containerNode()) {
+ if (!node->renderer())
+ p = lastPositionInOrAfterNode(node);
+ }
}
return Position();
}
Position previousVisuallyDistinctCandidate(const Position& position)
{
+ // FIXME: Use PositionIterator instead.
Position p = position;
Position downstreamStart = p.downstream();
while (!p.atStartOfTree()) {
p = p.previous(Character);
if (p.isCandidate() && p.downstream() != downstreamStart)
return p;
+ if (auto* node = p.containerNode()) {
+ if (!node->renderer())
+ p = firstPositionInOrBeforeNode(node);
+ }
}
return Position();
}