Skip to content

Commit c0671ac

Browse files
author
Chris Blumenberg
committed
WebCore:
Made markup copying 5 times faster. Unfortunately, this still doesn't fix: <rdar://problem/3794799> Tiger8A252: copying a bunch o' text is so slow it seems like a hang Reviewed by rjw. * khtml/dom/dom_string.h: * khtml/xml/dom2_rangeimpl.cpp: (DOM::RangeImpl::toHTML): serialize the range by iterating through the range * khtml/xml/dom_nodeimpl.cpp: (NodeImpl::startMarkup): new, factored out from recursive_toString (NodeImpl::endMarkup): ditto (NodeImpl::recursive_toString): call factored out methods * khtml/xml/dom_nodeimpl.h: WebKit: Reviewed by rjw. * WebView.subproj/WebHTMLView.m: (-[WebHTMLView _selectedArchive]): added timing code for copying markup Canonical link: https://commits.webkit.org/6700@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@7674 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent fd2752b commit c0671ac

7 files changed

Lines changed: 186 additions & 36 deletions

File tree

WebCore/ChangeLog-2005-08-23

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
2004-09-24 Chris Blumenberg <cblu@apple.com>
2+
3+
Made markup copying 5 times faster. Unfortunately, this still doesn't fix:
4+
<rdar://problem/3794799> Tiger8A252: copying a bunch o' text is so slow it seems like a hang
5+
6+
Reviewed by rjw.
7+
8+
* khtml/dom/dom_string.h:
9+
* khtml/xml/dom2_rangeimpl.cpp:
10+
(DOM::RangeImpl::toHTML): serialize the range by iterating through the range
11+
* khtml/xml/dom_nodeimpl.cpp:
12+
(NodeImpl::startMarkup): new, factored out from recursive_toString
13+
(NodeImpl::endMarkup): ditto
14+
(NodeImpl::recursive_toString): call factored out methods
15+
* khtml/xml/dom_nodeimpl.h:
16+
117
=== Safari-165 ===
218

319
2004-09-24 Ken Kocienda <kocienda@apple.com>

WebCore/khtml/dom/dom_string.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,10 @@ class DOMString
120120
operator NSString *() const;
121121
#endif
122122

123-
private:
123+
#ifndef NDEBUG
124124
// For debugging only, leaks memory.
125125
const char *ascii() const;
126+
#endif
126127

127128
protected:
128129
DOMStringImpl *impl;

WebCore/khtml/xml/dom2_rangeimpl.cpp

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,14 +824,119 @@ DOMString RangeImpl::toHTML(QPtrList<NodeImpl> *nodes) const
824824
{
825825
int exceptionCode;
826826
NodeImpl *commonAncestor = commonAncestorContainer(exceptionCode);
827-
NodeImpl *commonAncestorBlock = commonAncestor ? commonAncestor->enclosingBlockFlowElement() : 0;
828-
if (commonAncestorBlock == 0)
829-
return "";
827+
NodeImpl *commonAncestorBlock = 0;
828+
if (commonAncestor != 0) {
829+
commonAncestorBlock = commonAncestor->enclosingBlockFlowElement();
830+
}
831+
if (commonAncestorBlock == 0) {
832+
return "";
833+
}
834+
835+
#ifdef USE_NODEIMPL_ALGORITHM
830836
NodeImpl::Id id = commonAncestorBlock->id();
831837
bool onlyIncludeChildren = (id != ID_TABLE && id != ID_OL && id != ID_UL);
832838
return commonAncestorBlock->recursive_toHTML(onlyIncludeChildren, true, this, nodes);
839+
#else
840+
841+
QStringList markups;
842+
NodeImpl *pastEnd = pastEndNode();
843+
NodeImpl *lastClosed = 0;
844+
QPtrList<NodeImpl> ancestorsToClose;
845+
846+
// Iterate through the nodes of the range.
847+
for (NodeImpl *n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
848+
849+
// Add the node to the markup.
850+
markups.append(n->startMarkup(this));
851+
if (nodes) {
852+
nodes->append(n);
853+
}
854+
855+
if (n->firstChild() == 0) {
856+
// Node has no children, add its close tag now.
857+
markups.append(n->endMarkup());
858+
lastClosed = n;
859+
860+
// Check if the node is the last leaf of a tree.
861+
NodeImpl *parent = n->parentNode();
862+
if (parent != 0 && n == parent->lastChild()) {
863+
if (!ancestorsToClose.isEmpty()) {
864+
// Close up the ancestors.
865+
QPtrListIterator<NodeImpl> ancestorsToCloseIt(ancestorsToClose);
866+
NodeImpl *next = n->traverseNextNode();
867+
NodeImpl *ancestor;
868+
int removeCount = 0;
869+
for (ancestorsToCloseIt.toLast(); (ancestor = ancestorsToCloseIt.current()) != 0; --ancestorsToCloseIt) {
870+
if (next != pastEnd) {
871+
// Not at the end of the range, close ancestors up to sibling of next node.
872+
if (ancestor != next->parentNode()) {
873+
markups.append(ancestor->endMarkup());
874+
lastClosed = ancestor;
875+
removeCount++;
876+
} else {
877+
break;
878+
}
879+
} else {
880+
// At the end of the range, close all pending ancestors.
881+
markups.append(ancestor->endMarkup());
882+
lastClosed = ancestor;
883+
removeCount++;
884+
}
885+
}
886+
for (int i = removeCount; i > 0; i--) {
887+
ancestorsToClose.removeLast();
888+
}
889+
} else {
890+
// No ancestors to close, but need to add ancestors not in range since next node is in another tree.
891+
NodeImpl *next = n->traverseNextNode();
892+
if (next != pastEnd && n != next->parentNode()) {
893+
while (parent != 0 && parent != next->parentNode()) {
894+
markups.prepend(parent->startMarkup(this));
895+
markups.append(parent->endMarkup());
896+
if (nodes) {
897+
nodes->append(parent);
898+
}
899+
lastClosed = parent;
900+
parent = parent->parentNode();
901+
}
902+
}
903+
}
904+
}
905+
} else {
906+
// Node is an ancestor, set it to close eventually.
907+
ancestorsToClose.append(n);
908+
}
909+
}
910+
911+
// Add ancestors up to the common ancestor block so inline ancestors such as FONT and B are part of the markup.
912+
NodeImpl *ancestor = lastClosed->parentNode();
913+
while (ancestor) {
914+
bool breakAtEnd = false;
915+
if (commonAncestorBlock == ancestor) {
916+
NodeImpl::Id id = ancestor->id();
917+
// Tables and lists must be part of the markup to avoid broken structures.
918+
if (id == ID_TABLE || id == ID_OL || id == ID_UL) {
919+
breakAtEnd = true;
920+
} else {
921+
break;
922+
}
923+
}
924+
markups.prepend(ancestor->startMarkup(this));
925+
markups.append(ancestor->endMarkup());
926+
if (nodes) {
927+
nodes->append(ancestor);
928+
}
929+
if (breakAtEnd) {
930+
break;
931+
}
932+
ancestor = ancestor->parentNode();
933+
}
934+
935+
return markups.join("");
936+
#endif
833937
}
834938

939+
835940
DOMString RangeImpl::text() const
836941
{
837942
if (m_detached)

WebCore/khtml/xml/dom_nodeimpl.cpp

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,47 @@ static QString escapeHTML( const QString& in )
280280
return s;
281281
}
282282

283-
QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, const DOM::RangeImpl *range, QPtrList<NodeImpl> *nodes)
283+
QString NodeImpl::startMarkup(const DOM::RangeImpl *range) const
284+
{
285+
if (nodeType() == Node::TEXT_NODE) {
286+
DOMString str = nodeValue().copy();
287+
if (range) {
288+
int exceptionCode;
289+
if (this == range->endContainer(exceptionCode)) {
290+
str.truncate(range->endOffset(exceptionCode));
291+
}
292+
if (this == range->startContainer(exceptionCode)) {
293+
str.remove(0, range->startOffset(exceptionCode));
294+
}
295+
}
296+
Id parentID = parentNode()->id();
297+
bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
298+
return dontEscape ? str.string() : escapeHTML(str.string());
299+
} else {
300+
QString markup = QChar('<') + nodeName().string();
301+
if (nodeType() == Node::ELEMENT_NODE) {
302+
const ElementImpl *el = static_cast<const ElementImpl *>(this);
303+
NamedAttrMapImpl *attrs = el->attributes();
304+
unsigned long length = attrs->length();
305+
for (unsigned int i=0; i<length; i++) {
306+
AttributeImpl *attr = attrs->attributeItem(i);
307+
markup += " " + getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\"";
308+
}
309+
}
310+
markup += isHTMLElement() ? ">" : "/>";
311+
return markup;
312+
}
313+
}
314+
315+
QString NodeImpl::endMarkup(void) const
316+
{
317+
if ((!isHTMLElement() || endTag[id()] != FORBIDDEN) && nodeType() != Node::TEXT_NODE && nodeType() != Node::DOCUMENT_NODE) {
318+
return "</" + nodeName().string() + ">";
319+
}
320+
return "";
321+
}
284322

323+
QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, const DOM::RangeImpl *range, QPtrList<NodeImpl> *nodes)
285324
{
286325
QString me = "";
287326

@@ -311,35 +350,7 @@ QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyInclude
311350
if (nodes) {
312351
nodes->append(current);
313352
}
314-
// Copy who I am into the me string
315-
if (current->nodeType() == Node::TEXT_NODE) {
316-
DOMString str = current->nodeValue().copy();
317-
if (range) {
318-
int exceptionCode;
319-
if (current == range->endContainer(exceptionCode)) {
320-
str.truncate(range->endOffset(exceptionCode));
321-
}
322-
if (current == range->startContainer(exceptionCode)) {
323-
str.remove(0, range->startOffset(exceptionCode));
324-
}
325-
}
326-
Id parentID = current->parentNode()->id();
327-
bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
328-
me += dontEscape ? str.string() : escapeHTML(str.string());
329-
} else if (current->nodeType() != Node::DOCUMENT_NODE) {
330-
// If I am an element, not a text
331-
me += QChar('<') + current->nodeName().string();
332-
if (current->nodeType() == Node::ELEMENT_NODE) {
333-
const ElementImpl *el = static_cast<const ElementImpl *>(current);
334-
NamedAttrMapImpl *attrs = el->attributes();
335-
unsigned long length = attrs->length();
336-
for (unsigned int i=0; i<length; i++) {
337-
AttributeImpl *attr = attrs->attributeItem(i);
338-
me += " " + current->getDocument()->attrName(attr->id()).string() + "=\"" + attr->value().string() + "\"";
339-
}
340-
}
341-
me += current->isHTMLElement() ? ">" : "/>";
342-
}
353+
me += current->startMarkup(range);
343354
}
344355

345356
if (!current->isHTMLElement() || endTag[current->id()] != FORBIDDEN) {
@@ -348,8 +359,8 @@ QString NodeImpl::recursive_toString(const NodeImpl *startNode, bool onlyInclude
348359
me += recursive_toString(n, false, true, range, nodes);
349360
}
350361
// Print my ending tag
351-
if (include && current->nodeType() != Node::TEXT_NODE && current->nodeType() != Node::DOCUMENT_NODE) {
352-
me += "</" + current->nodeName().string() + ">";
362+
if (include) {
363+
me += current->endMarkup();
353364
}
354365
}
355366

WebCore/khtml/xml/dom_nodeimpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ class NodeImpl : public khtml::TreeShared<NodeImpl>
259259
virtual bool isMouseFocusable() const;
260260

261261
virtual bool isInline() const;
262+
QString startMarkup(const DOM::RangeImpl *range) const;
263+
QString endMarkup(void) const;
262264
virtual QString toHTML() const;
263265
QString recursive_toHTML(bool onlyIncludeChildren=false, bool includeSiblings = false, const DOM::RangeImpl *range=NULL, QPtrList<NodeImpl> *nodes=NULL) const;
264266
static QString recursive_toString(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, const DOM::RangeImpl *range, QPtrList<NodeImpl> *nodes);

WebKit/ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2004-09-24 Chris Blumenberg <cblu@apple.com>
2+
3+
Reviewed by rjw.
4+
5+
* WebView.subproj/WebHTMLView.m:
6+
(-[WebHTMLView _selectedArchive]): added timing code for copying markup
7+
18
=== Safari-165 ===
29

310
2004-09-24 Chris Blumenberg <cblu@apple.com>

WebKit/WebView.subproj/WebHTMLView.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,15 @@ + (NSArray *)_selectionPasteboardTypes
833833
- (WebArchive *)_selectedArchive
834834
{
835835
NSArray *nodes;
836+
#if !LOG_DISABLED
837+
double start = CFAbsoluteTimeGetCurrent();
838+
#endif
836839
NSString *markupString = [[self _bridge] markupStringFromRange:[self _selectedRange] nodes:&nodes];
840+
#if !LOG_DISABLED
841+
double duration = CFAbsoluteTimeGetCurrent() - start;
842+
LOG(Timing, "copying markup took %f seconds.", duration);
843+
#endif
844+
837845
return [[self _dataSource] _archiveWithMarkupString:markupString nodes:nodes];
838846
}
839847

0 commit comments

Comments
 (0)