Diff
Modified: trunk/Source/WebCore/CMakeLists.txt (154239 => 154240)
--- trunk/Source/WebCore/CMakeLists.txt 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/CMakeLists.txt 2013-08-17 21:33:23 UTC (rev 154240)
@@ -1230,6 +1230,7 @@
dom/TagNodeList.cpp
dom/Text.cpp
dom/TextEvent.cpp
+ dom/TextNodeTraversal.cpp
dom/Touch.cpp
dom/TouchEvent.cpp
dom/TouchList.cpp
Modified: trunk/Source/WebCore/ChangeLog (154239 => 154240)
--- trunk/Source/WebCore/ChangeLog 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/ChangeLog 2013-08-17 21:33:23 UTC (rev 154240)
@@ -1,3 +1,52 @@
+2013-08-17 Antti Koivisto <[email protected]>
+
+ <https://webkit.org/b/119959> Add TextNodeTraversal
+
+ Reviewed by Andreas Kling.
+
+ Add TextNodeTraversal for cleaner and more compact traversal of Text nodes.
+
+ Use it where appropriate.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * dom/Attr.cpp:
+ (WebCore::Attr::childrenChanged):
+ * dom/NodeTraversal.h:
+ (WebCore::NodeTraversal::next):
+ * dom/ScriptElement.cpp:
+ (WebCore::ScriptElement::scriptContent):
+ * dom/Text.cpp:
+ (WebCore::Text::wholeText):
+ * dom/Text.h:
+ (WebCore::toText):
+ * dom/TextNodeTraversal.cpp: Added.
+ (WebCore::TextNodeTraversal::appendContents):
+ (WebCore::TextNodeTraversal::contentsAsString):
+
+ Helpers for getting text content of a subtree.
+
+ * dom/TextNodeTraversal.h: Added.
+ (WebCore::TextNodeTraversal::firstTextChildTemplate):
+ (WebCore::TextNodeTraversal::firstChild):
+ (WebCore::TextNodeTraversal::firstTextWithinTemplate):
+ (WebCore::TextNodeTraversal::firstWithin):
+ (WebCore::TextNodeTraversal::traverseNextTextTemplate):
+ (WebCore::TextNodeTraversal::next):
+ (WebCore::TextNodeTraversal::nextSibling):
+ * editing/ApplyStyleCommand.cpp:
+ (WebCore::ApplyStyleCommand::joinChildTextNodes):
+ * html/HTMLTextAreaElement.cpp:
+ (WebCore::HTMLTextAreaElement::defaultValue):
+ (WebCore::HTMLTextAreaElement::setDefaultValue):
+ * html/HTMLTitleElement.cpp:
+ (WebCore::HTMLTitleElement::text):
+ * html/track/TextTrackCue.cpp:
+ (WebCore::TextTrackCue::determineTextDirection):
+ * page/Frame.cpp:
+ (WebCore::Frame::searchForLabelsAboveCell):
+ * xml/XPathUtil.cpp:
+ (WebCore::XPath::stringValue):
+
2013-08-17 Andreas Kling <[email protected]>
<https://webkit.org/b/119957> Page::contextMenuController() should return a reference.
Modified: trunk/Source/WebCore/GNUmakefile.list.am (154239 => 154240)
--- trunk/Source/WebCore/GNUmakefile.list.am 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/GNUmakefile.list.am 2013-08-17 21:33:23 UTC (rev 154240)
@@ -3042,6 +3042,8 @@
Source/WebCore/dom/TextEvent.cpp \
Source/WebCore/dom/TextEvent.h \
Source/WebCore/dom/TextEventInputType.h \
+ Source/WebCore/dom/TextNodeTraversal.cpp \
+ Source/WebCore/dom/TextNodeTraversal.h \
Source/WebCore/dom/Text.h \
Source/WebCore/dom/Touch.h \
Source/WebCore/dom/TouchEvent.h \
Modified: trunk/Source/WebCore/Target.pri (154239 => 154240)
--- trunk/Source/WebCore/Target.pri 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/Target.pri 2013-08-17 21:33:23 UTC (rev 154240)
@@ -477,6 +477,7 @@
dom/TagNodeList.cpp \
dom/Text.cpp \
dom/TextEvent.cpp \
+ dom/TextNodeTraversal.cpp \
dom/Touch.cpp \
dom/TouchEvent.cpp \
dom/TouchList.cpp \
@@ -1677,6 +1678,7 @@
dom/TagNodeList.h \
dom/TemplateContentDocumentFragment.h \
dom/TextEvent.h \
+ dom/TextNodeTraversal.h \
dom/TextEventInputType.h \
dom/Text.h \
dom/Touch.h \
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (154239 => 154240)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2013-08-17 21:33:23 UTC (rev 154240)
@@ -13377,6 +13377,20 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="..\dom\TextNodeTraversal.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug_WinCairo|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug_WinCairo|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WinCairo|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WinCairo|x64'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
+ </ClCompile>
<ClCompile Include="..\dom\TransformSourceLibxslt.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -20311,6 +20325,7 @@
<ClInclude Include="..\dom\TemplateContentDocumentFragment.h" />
<ClInclude Include="..\dom\Text.h" />
<ClInclude Include="..\dom\TextEvent.h" />
+ <ClInclude Include="..\dom\TextNodeTraversal.h" />
<ClInclude Include="..\dom\TextEventInputType.h" />
<ClInclude Include="..\dom\TransformSource.h" />
<ClInclude Include="..\dom\Traversal.h" />
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (154239 => 154240)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-08-17 21:33:23 UTC (rev 154240)
@@ -5525,6 +5525,8 @@
E4D58EBB17B8F12800CBDCA8 /* ElementTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */; };
E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */; };
E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */; };
+ E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */; };
+ E4D988B617BFEB210084FB88 /* TextNodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */; };
E4DEAA1717A93DC3000E0430 /* StyleResolveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */; };
E4DEAA1817A93DC3000E0430 /* StyleResolveTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E4DEAA1617A93DC3000E0430 /* StyleResolveTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4F9EEF2156D9FFA00D23E7E /* StyleSheetContents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */; };
@@ -12313,6 +12315,8 @@
E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementTraversal.h; sourceTree = "<group>"; };
E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PurgeableBufferMac.cpp; sourceTree = "<group>"; };
E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgeableBuffer.h; sourceTree = "<group>"; };
+ E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextNodeTraversal.h; sourceTree = "<group>"; };
+ E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextNodeTraversal.cpp; sourceTree = "<group>"; };
E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleResolveTree.cpp; sourceTree = "<group>"; };
E4DEAA1617A93DC3000E0430 /* StyleResolveTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleResolveTree.h; sourceTree = "<group>"; };
E4F9EEF0156D84C400D23E7E /* StyleSheetContents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleSheetContents.cpp; sourceTree = "<group>"; };
@@ -20434,6 +20438,8 @@
933A142D0B7D188600A53FFD /* TextEvent.h */,
933A142C0B7D188600A53FFD /* TextEvent.idl */,
A77B419F12E675A90054343D /* TextEventInputType.h */,
+ E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */,
+ E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */,
5DB1BC6810715A6400EFAA49 /* TransformSource.h */,
5DB1BC6910715A6400EFAA49 /* TransformSourceLibxslt.cpp */,
E17B491316A9B093001C8839 /* TransitionEvent.cpp */,
@@ -22637,6 +22643,7 @@
BE8EF04D171C9014009B48C3 /* JSVideoTrackList.h in Headers */,
FD82D7F813D4C8BD004E4372 /* JSWaveShaperNode.h in Headers */,
A7D20F63107F406900A80392 /* JSWebGLActiveInfo.h in Headers */,
+ E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */,
49C7B9941042D2D30009D447 /* JSWebGLBuffer.h in Headers */,
7EA30F6A16DFFE7500257D0B /* JSWebGLCompressedTextureATC.h in Headers */,
7EA30F6A17EFFE7500257D0B /* JSWebGLCompressedTexturePVRTC.h in Headers */,
@@ -26455,6 +26462,7 @@
511F23190DC160DA004F0032 /* StorageThread.cpp in Sources */,
3AB02D2B12D4F91600FBB694 /* StorageTracker.cpp in Sources */,
8102C5881325BB1100DDE67A /* StringCallback.cpp in Sources */,
+ E4D988B617BFEB210084FB88 /* TextNodeTraversal.cpp in Sources */,
B2B2645C0D00A77E000ACC1D /* StringCF.cpp in Sources */,
B2B2645D0D00A77E000ACC1D /* StringImplCF.cpp in Sources */,
B2AFFC950D00A5DF0030074D /* StringImplMac.mm in Sources */,
Modified: trunk/Source/WebCore/dom/Attr.cpp (154239 => 154240)
--- trunk/Source/WebCore/dom/Attr.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/dom/Attr.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -29,6 +29,7 @@
#include "StylePropertySet.h"
#include "StyledElement.h"
#include "Text.h"
+#include "TextNodeTraversal.h"
#include "XMLNSNames.h"
#include <wtf/text/AtomicString.h>
#include <wtf/text/StringBuilder.h>
@@ -165,13 +166,8 @@
invalidateNodeListCachesInAncestors(&qualifiedName(), m_element);
- // FIXME: We should include entity references in the value
-
StringBuilder valueBuilder;
- for (Node *n = firstChild(); n; n = n->nextSibling()) {
- if (n->isTextNode())
- valueBuilder.append(toText(n)->data());
- }
+ TextNodeTraversal::appendContents(this, valueBuilder);
AtomicString newValue = valueBuilder.toAtomicString();
if (m_element)
Modified: trunk/Source/WebCore/dom/DOMAllInOne.cpp (154239 => 154240)
--- trunk/Source/WebCore/dom/DOMAllInOne.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/dom/DOMAllInOne.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -135,6 +135,7 @@
#include "TagNodeList.cpp"
#include "Text.cpp"
#include "TextEvent.cpp"
+#include "TextNodeTraversal.cpp"
#include "Touch.cpp"
#include "TouchEvent.cpp"
#include "TouchList.cpp"
Modified: trunk/Source/WebCore/dom/NodeTraversal.h (154239 => 154240)
--- trunk/Source/WebCore/dom/NodeTraversal.h 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/dom/NodeTraversal.h 2013-08-17 21:33:23 UTC (rev 154240)
@@ -26,6 +26,7 @@
#define NodeTraversal_h
#include "Node.h"
+#include "Text.h"
namespace WebCore {
namespace NodeTraversal {
@@ -38,6 +39,8 @@
Node* next(const Node*, const Node* stayWithin);
Node* next(const ContainerNode*);
Node* next(const ContainerNode*, const Node* stayWithin);
+Node* next(const Text*);
+Node* next(const Text*, const Node* stayWithin);
// Like next, but skips children and starts with the next sibling.
Node* nextSkippingChildren(const Node*);
@@ -81,7 +84,7 @@
}
inline Node* next(const Node* current) { return traverseNextTemplate(current); }
inline Node* next(const ContainerNode* current) { return traverseNextTemplate(current); }
-
+
template <class NodeType>
inline Node* traverseNextTemplate(NodeType* current, const Node* stayWithin)
{
@@ -118,6 +121,9 @@
inline Node* nextSkippingChildren(const Node* current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
inline Node* nextSkippingChildren(const ContainerNode* current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
+inline Node* next(const Text* current) { return traverseNextSkippingChildrenTemplate(current); }
+inline Node* next(const Text* current, const Node* stayWithin) { return traverseNextSkippingChildrenTemplate(current, stayWithin); }
+
}
}
Modified: trunk/Source/WebCore/dom/ScriptElement.cpp (154239 => 154240)
--- trunk/Source/WebCore/dom/ScriptElement.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/dom/ScriptElement.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -50,6 +50,7 @@
#include "SecurityOrigin.h"
#include "Settings.h"
#include "Text.h"
+#include "TextNodeTraversal.h"
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringHash.h>
@@ -397,19 +398,15 @@
Text* firstTextNode = 0;
bool foundMultipleTextNodes = false;
- for (Node* n = m_element->firstChild(); n; n = n->nextSibling()) {
- if (!n->isTextNode())
- continue;
-
- Text* t = toText(n);
+ for (Text* textNode = TextNodeTraversal::firstChild(m_element); textNode; textNode = TextNodeTraversal::nextSibling(textNode)) {
if (foundMultipleTextNodes)
- content.append(t->data());
+ content.append(textNode->data());
else if (firstTextNode) {
content.append(firstTextNode->data());
- content.append(t->data());
+ content.append(textNode->data());
foundMultipleTextNodes = true;
} else
- firstTextNode = t;
+ firstTextNode = textNode;
}
if (firstTextNode && !foundMultipleTextNodes)
Modified: trunk/Source/WebCore/dom/Text.cpp (154239 => 154240)
--- trunk/Source/WebCore/dom/Text.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/dom/Text.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -29,6 +29,7 @@
#include "RenderText.h"
#include "ScopedEventQueue.h"
#include "ShadowRoot.h"
+#include "TextNodeTraversal.h"
#if ENABLE(SVG)
#include "RenderSVGInlineText.h"
@@ -93,38 +94,26 @@
return newText.release();
}
-static const Text* earliestLogicallyAdjacentTextNode(const Text* t)
+static const Text* earliestLogicallyAdjacentTextNode(const Text* text)
{
- const Node* n = t;
- while ((n = n->previousSibling())) {
- Node::NodeType type = n->nodeType();
- if (type == Node::TEXT_NODE || type == Node::CDATA_SECTION_NODE) {
- t = static_cast<const Text*>(n);
- continue;
- }
-
- // We would need to visit EntityReference child text nodes if they existed
- ASSERT(type != Node::ENTITY_REFERENCE_NODE || !n->hasChildNodes());
- break;
+ const Node* node = text;
+ while ((node = node->previousSibling())) {
+ if (!node->isTextNode())
+ break;
+ text = toText(node);
}
- return t;
+ return text;
}
-static const Text* latestLogicallyAdjacentTextNode(const Text* t)
+static const Text* latestLogicallyAdjacentTextNode(const Text* text)
{
- const Node* n = t;
- while ((n = n->nextSibling())) {
- Node::NodeType type = n->nodeType();
- if (type == Node::TEXT_NODE || type == Node::CDATA_SECTION_NODE) {
- t = static_cast<const Text*>(n);
- continue;
- }
-
- // We would need to visit EntityReference child text nodes if they existed
- ASSERT(type != Node::ENTITY_REFERENCE_NODE || !n->hasChildNodes());
- break;
+ const Node* node = text;
+ while ((node = node->nextSibling())) {
+ if (!node->isTextNode())
+ break;
+ text = toText(node);
}
- return t;
+ return text;
}
String Text::wholeText() const
@@ -132,23 +121,15 @@
const Text* startText = earliestLogicallyAdjacentTextNode(this);
const Text* endText = latestLogicallyAdjacentTextNode(this);
- Node* _onePastEndText_ = endText->nextSibling();
+ Node* _onePastEndText_ = TextNodeTraversal::nextSibling(endText);
Checked<unsigned> resultLength = 0;
- for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) {
- if (!n->isTextNode())
- continue;
- const Text* t = static_cast<const Text*>(n);
- const String& data = ""
- resultLength += data.length();
- }
+ for (const Text* text = startText; text != onePastEndText; text = TextNodeTraversal::nextSibling(text))
+ resultLength += text->length();
+
StringBuilder result;
result.reserveCapacity(resultLength.unsafeGet());
- for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) {
- if (!n->isTextNode())
- continue;
- const Text* t = static_cast<const Text*>(n);
- result.append(t->data());
- }
+ for (const Text* text = startText; text != onePastEndText; text = TextNodeTraversal::nextSibling(text))
+ result.append(text->data());
ASSERT(result.length() == resultLength.unsafeGet());
return result.toString();
Modified: trunk/Source/WebCore/dom/Text.h (154239 => 154240)
--- trunk/Source/WebCore/dom/Text.h 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/dom/Text.h 2013-08-17 21:33:23 UTC (rev 154240)
@@ -84,6 +84,12 @@
return static_cast<Text*>(node);
}
+inline const Text* toText(const Node* node)
+{
+ ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isTextNode());
+ return static_cast<const Text*>(node);
+}
+
} // namespace WebCore
#endif // Text_h
Added: trunk/Source/WebCore/dom/TextNodeTraversal.cpp (0 => 154240)
--- trunk/Source/WebCore/dom/TextNodeTraversal.cpp (rev 0)
+++ trunk/Source/WebCore/dom/TextNodeTraversal.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TextNodeTraversal.h"
+
+#include "ContainerNode.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+namespace TextNodeTraversal {
+
+void appendContents(const ContainerNode* root, StringBuilder& result)
+{
+ for (Text* text = TextNodeTraversal::firstWithin(root); text; text = TextNodeTraversal::next(text, root))
+ result.append(text->data());
+}
+
+String contentsAsString(const ContainerNode* root)
+{
+ StringBuilder result;
+ appendContents(root, result);
+ return result.toString();
+}
+
+String contentsAsString(const Node* root)
+{
+ if (root->isTextNode())
+ return toText(root)->data();
+ if (root->isContainerNode())
+ return contentsAsString(toContainerNode(root));
+ return String();
+}
+
+}
+}
Added: trunk/Source/WebCore/dom/TextNodeTraversal.h (0 => 154240)
--- trunk/Source/WebCore/dom/TextNodeTraversal.h (rev 0)
+++ trunk/Source/WebCore/dom/TextNodeTraversal.h 2013-08-17 21:33:23 UTC (rev 154240)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextNodeTraversal_h
+#define TextNodeTraversal_h
+
+#include "NodeTraversal.h"
+#include "Text.h"
+
+namespace WTF {
+class StringBuilder;
+}
+
+namespace WebCore {
+namespace TextNodeTraversal {
+
+// First text child of the node.
+Text* firstChild(const Node*);
+Text* firstChild(const ContainerNode*);
+
+// First text descendant of the node.
+Text* firstWithin(const Node*);
+Text* firstWithin(const ContainerNode*);
+
+// Pre-order traversal skipping non-text nodes.
+Text* next(const Node*);
+Text* next(const Node*, const Node* stayWithin);
+Text* next(const Text*);
+Text* next(const Text*, const Node* stayWithin);
+
+// Next text sibling.
+Text* nextSibling(const Node*);
+
+// Concatenated text contents of a subtree.
+String contentsAsString(const Node*);
+String contentsAsString(const ContainerNode*);
+void appendContents(const ContainerNode*, StringBuilder& result);
+
+}
+
+namespace TextNodeTraversal {
+
+template <class NodeType>
+inline Text* firstTextChildTemplate(NodeType* current)
+{
+ Node* node = current->firstChild();
+ while (node && !node->isTextNode())
+ node = node->nextSibling();
+ return toText(node);
+}
+inline Text* firstChild(const Node* current) { return firstTextChildTemplate(current); }
+inline Text* firstChild(const ContainerNode* current) { return firstTextChildTemplate(current); }
+
+template <class NodeType>
+inline Text* firstTextWithinTemplate(NodeType* current)
+{
+ Node* node = current->firstChild();
+ while (node && !node->isTextNode())
+ node = NodeTraversal::next(node, current);
+ return toText(node);
+}
+inline Text* firstWithin(const Node* current) { return firstTextWithinTemplate(current); }
+inline Text* firstWithin(const ContainerNode* current) { return firstTextWithinTemplate(current); }
+
+template <class NodeType>
+inline Text* traverseNextTextTemplate(NodeType* current)
+{
+ Node* node = NodeTraversal::next(current);
+ while (node && !node->isTextNode())
+ node = NodeTraversal::next(node);
+ return toText(node);
+}
+inline Text* next(const Node* current) { return traverseNextTextTemplate(current); }
+inline Text* next(const Text* current) { return traverseNextTextTemplate(current); }
+
+template <class NodeType>
+inline Text* traverseNextTextTemplate(NodeType* current, const Node* stayWithin)
+{
+ Node* node = NodeTraversal::next(current, stayWithin);
+ while (node && !node->isTextNode())
+ node = NodeTraversal::next(node, stayWithin);
+ return toText(node);
+}
+inline Text* next(const Node* current, const Node* stayWithin) { return traverseNextTextTemplate(current, stayWithin); }
+inline Text* next(const Text* current, const Node* stayWithin) { return traverseNextTextTemplate(current, stayWithin); }
+
+inline Text* nextSibling(const Node* current)
+{
+ Node* node = current->nextSibling();
+ while (node && !node->isTextNode())
+ node = node->nextSibling();
+ return toText(node);
+}
+
+}
+}
+
+#endif
Modified: trunk/Source/WebCore/editing/ApplyStyleCommand.cpp (154239 => 154240)
--- trunk/Source/WebCore/editing/ApplyStyleCommand.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/editing/ApplyStyleCommand.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -48,6 +48,7 @@
#include "StyleResolver.h"
#include "Text.h"
#include "TextIterator.h"
+#include "TextNodeTraversal.h"
#include "VisibleUnits.h"
#include "htmlediting.h"
#include <wtf/StdLibExtras.h>
@@ -1521,13 +1522,9 @@
Position newStart = start;
Position newEnd = end;
- Vector<RefPtr<Text> > textNodes;
- for (Node* curr = node->firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isTextNode())
- continue;
-
- textNodes.append(toText(curr));
- }
+ Vector<RefPtr<Text>> textNodes;
+ for (Text* textNode = TextNodeTraversal::firstChild(node); textNode; textNode = TextNodeTraversal::nextSibling(textNode))
+ textNodes.append(textNode);
for (size_t i = 0; i < textNodes.size(); ++i) {
Text* childText = textNodes[i].get();
Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.cpp (154239 => 154240)
--- trunk/Source/WebCore/html/HTMLTextAreaElement.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -47,6 +47,7 @@
#include "Text.h"
#include "TextControlInnerElements.h"
#include "TextIterator.h"
+#include "TextNodeTraversal.h"
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringBuilder.h>
@@ -399,15 +400,7 @@
String HTMLTextAreaElement::defaultValue() const
{
- StringBuilder value;
-
- // Since there may be comments, ignore nodes other than text nodes.
- for (Node* n = firstChild(); n; n = n->nextSibling()) {
- if (n->isTextNode())
- value.append(toText(n)->data());
- }
-
- return value.toString();
+ return TextNodeTraversal::contentsAsString(this);
}
void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
@@ -415,11 +408,10 @@
RefPtr<Node> protectFromMutationEvents(this);
// To preserve comments, remove only the text nodes, then add a single text node.
- Vector<RefPtr<Node> > textNodes;
- for (Node* n = firstChild(); n; n = n->nextSibling()) {
- if (n->isTextNode())
- textNodes.append(n);
- }
+ Vector<RefPtr<Text>> textNodes;
+ for (Text* textNode = TextNodeTraversal::firstChild(this); textNode; textNode = TextNodeTraversal::nextSibling(textNode))
+ textNodes.append(textNode);
+
size_t size = textNodes.size();
for (size_t i = 0; i < size; ++i)
removeChild(textNodes[i].get(), IGNORE_EXCEPTION);
Modified: trunk/Source/WebCore/html/HTMLTitleElement.cpp (154239 => 154240)
--- trunk/Source/WebCore/html/HTMLTitleElement.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/html/HTMLTitleElement.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -28,6 +28,7 @@
#include "RenderStyle.h"
#include "StyleInheritedData.h"
#include "Text.h"
+#include "TextNodeTraversal.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -74,14 +75,7 @@
String HTMLTitleElement::text() const
{
- StringBuilder result;
-
- for (Node *n = firstChild(); n; n = n->nextSibling()) {
- if (n->isTextNode())
- result.append(toText(n)->data());
- }
-
- return result.toString();
+ return TextNodeTraversal::contentsAsString(this);
}
StringWithDirection HTMLTitleElement::textWithDirection()
Modified: trunk/Source/WebCore/html/track/TextTrackCue.cpp (154239 => 154240)
--- trunk/Source/WebCore/html/track/TextTrackCue.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/html/track/TextTrackCue.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -632,6 +632,7 @@
// their descendants.
StringBuilder paragraphBuilder;
for (Node* node = m_webVTTNodeTree->firstChild(); node; node = NodeTraversal::next(node, m_webVTTNodeTree.get())) {
+ // FIXME: The code does not match the comment above. This does not actually exclude Ruby Text Object descendant.
if (!node->isTextNode() || node->localName() == rtTag)
continue;
Modified: trunk/Source/WebCore/page/Frame.cpp (154239 => 154240)
--- trunk/Source/WebCore/page/Frame.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/page/Frame.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -89,6 +89,7 @@
#include "Settings.h"
#include "StylePropertySet.h"
#include "TextIterator.h"
+#include "TextNodeTraversal.h"
#include "TextResourceDecoder.h"
#include "UserContentURLPattern.h"
#include "UserTypingGestureIndicator.h"
@@ -368,18 +369,18 @@
if (aboveCell) {
// search within the above cell we found for a match
size_t lengthSearched = 0;
- for (Node* n = aboveCell->firstChild(); n; n = NodeTraversal::next(n, aboveCell)) {
- if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
- // For each text chunk, run the regexp
- String nodeString = n->nodeValue();
- int pos = regExp->searchRev(nodeString);
- if (pos >= 0) {
- if (resultDistanceFromStartOfCell)
- *resultDistanceFromStartOfCell = lengthSearched;
- return nodeString.substring(pos, regExp->matchedLength());
- }
- lengthSearched += nodeString.length();
+ for (Text* textNode = TextNodeTraversal::firstWithin(aboveCell); textNode; textNode = TextNodeTraversal::next(textNode, aboveCell)) {
+ if (!textNode->renderer() || textNode->renderer()->style()->visibility() != VISIBLE)
+ continue;
+ // For each text chunk, run the regexp
+ String nodeString = textNode->data();
+ int pos = regExp->searchRev(nodeString);
+ if (pos >= 0) {
+ if (resultDistanceFromStartOfCell)
+ *resultDistanceFromStartOfCell = lengthSearched;
+ return nodeString.substring(pos, regExp->matchedLength());
}
+ lengthSearched += nodeString.length();
}
}
Modified: trunk/Source/WebCore/xml/XPathUtil.cpp (154239 => 154240)
--- trunk/Source/WebCore/xml/XPathUtil.cpp 2013-08-17 19:46:45 UTC (rev 154239)
+++ trunk/Source/WebCore/xml/XPathUtil.cpp 2013-08-17 21:33:23 UTC (rev 154240)
@@ -28,7 +28,7 @@
#include "XPathUtil.h"
#include "ContainerNode.h"
-#include "NodeTraversal.h"
+#include "TextNodeTraversal.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
@@ -50,21 +50,9 @@
case Node::XPATH_NAMESPACE_NODE:
return node->nodeValue();
default:
- if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) {
- StringBuilder result;
- result.reserveCapacity(1024);
-
- for (Node* n = node->firstChild(); n; n = NodeTraversal::next(n, node)) {
- if (n->isTextNode()) {
- const String& nodeValue = n->nodeValue();
- result.append(nodeValue);
- }
- }
-
- return result.toString();
- }
+ if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE)
+ return TextNodeTraversal::contentsAsString(node);
}
-
return String();
}