Index: WebCore/dom/Range.cpp |
=================================================================== |
--- WebCore/dom/Range.cpp (revision 75431) |
+++ WebCore/dom/Range.cpp (working copy) |
@@ -41,9 +41,12 @@ |
#include <stdio.h> |
#include <wtf/text/CString.h> |
#include <wtf/RefCountedLeakCounter.h> |
+#include <wtf/Vector.h> |
namespace WebCore { |
+typedef Vector<RefPtr<Node> > NodeVector; |
+ |
using namespace std; |
#ifndef NDEBUG |
@@ -595,9 +598,6 @@ |
PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec) |
{ |
- // FIXME: To work properly with mutation events, we will have to take into account |
- // situations where the tree is being transformed while we work on it - ugh! |
- |
RefPtr<DocumentFragment> fragment; |
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
fragment = DocumentFragment::create(m_ownerDocument.get()); |
@@ -655,21 +655,20 @@ |
pi->setData(data, ec); |
} |
} else { |
- Node* n = m_start.container()->firstChild(); |
+ RefPtr<Node> n = m_start.container()->firstChild(); |
int i; |
for (i = 0; n && i < m_start.offset(); i++) // skip until start offset |
n = n->nextSibling(); |
int endOffset = m_end.offset(); |
- while (n && i < endOffset) { // delete until end offset |
- Node* next = n->nextSibling(); |
+ RefPtr<Node> next; |
+ for (; n && i < endOffset; n = next, i++) { // delete until end offset |
+ next = n->nextSibling(); |
if (action == EXTRACT_CONTENTS) |
fragment->appendChild(n, ec); // will remove n from its parent |
else if (action == CLONE_CONTENTS) |
fragment->appendChild(n->cloneNode(true), ec); |
else |
- toContainerNode(m_start.container())->removeChild(n, ec); |
- n = next; |
- i++; |
+ toContainerNode(m_start.container())->removeChild(n.get(), ec); |
} |
} |
return fragment.release(); |
@@ -720,39 +719,47 @@ |
} else { |
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) |
leftContents = m_start.container()->cloneNode(false); |
+ NodeVector nodes; |
Node* n = m_start.container()->firstChild(); |
- for (int i = 0; n && i < m_start.offset(); i++) // skip until start offset |
- n = n->nextSibling(); |
- while (n) { // process until end |
- Node* next = n->nextSibling(); |
+ for (int i = 0; n; n = n->nextSibling(), i++) { |
+ if (i < m_start.offset()) |
+ continue; // Skip until start offset. |
+ nodes.append(n); |
+ } |
+ for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) { |
+ Node* n = it->get(); |
if (action == EXTRACT_CONTENTS) |
- leftContents->appendChild(n, ec); // will remove n from start container |
+ leftContents->appendChild(n, ec); // Will remove n from start container. |
else if (action == CLONE_CONTENTS) |
leftContents->appendChild(n->cloneNode(true), ec); |
else |
toContainerNode(m_start.container())->removeChild(n, ec); |
- n = next; |
} |
} |
- ContainerNode* leftParent = m_start.container()->parentNode(); |
- Node* n = m_start.container()->nextSibling(); |
- for (; leftParent != commonRoot; leftParent = leftParent->parentNode()) { |
+ NodeVector ancestorNodes; |
+ for (ContainerNode* n = m_start.container()->parentNode(); n && n != commonRoot; n = n->parentNode()) |
+ ancestorNodes.append(n); |
+ RefPtr<Node> n = m_start.container()->nextSibling(); |
+ for (NodeVector::const_iterator it = ancestorNodes.begin(); it != ancestorNodes.end(); it++) { |
+ Node* leftParent = it->get(); |
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { |
RefPtr<Node> leftContentsParent = leftParent->cloneNode(false); |
- leftContentsParent->appendChild(leftContents, ec); |
- leftContents = leftContentsParent; |
+ if (leftContentsParent) { // Might have been removed already during mutation event. |
+ leftContentsParent->appendChild(leftContents, ec); |
+ leftContents = leftContentsParent; |
+ } |
} |
- Node* next; |
+ RefPtr<Node> next; |
for (; n; n = next) { |
next = n->nextSibling(); |
if (action == EXTRACT_CONTENTS) |
- leftContents->appendChild(n, ec); // will remove n from leftParent |
+ leftContents->appendChild(n.get(), ec); // will remove n from leftParent |
else if (action == CLONE_CONTENTS) |
leftContents->appendChild(n->cloneNode(true), ec); |
else |
- leftParent->removeChild(n, ec); |
+ leftParent->removeChild(n.get(), ec); |
} |
n = leftParent->nextSibling(); |
} |
@@ -786,15 +793,12 @@ |
rightContents = m_end.container()->cloneNode(false); |
Node* n = m_end.container()->firstChild(); |
if (n && m_end.offset()) { |
- for (int i = 0; i + 1 < m_end.offset(); i++) { // skip to end.offset() |
- Node* next = n->nextSibling(); |
- if (!next) |
- break; |
- n = next; |
+ NodeVector nodes; |
+ for (int i = 0; i + 1 < m_end.offset() && n; i++, n = n->nextSibling()) { |
+ nodes.append(n); |
} |
- Node* prev; |
- for (; n; n = prev) { |
- prev = n->previousSibling(); |
+ for (int i = nodes.size() - 1; i >= 0; i--) { |
+ Node* n = nodes[i].get(); |
if (action == EXTRACT_CONTENTS) |
rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent |
else if (action == CLONE_CONTENTS) |
@@ -868,11 +872,12 @@ |
if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents) |
fragment->appendChild(leftContents, ec); |
- Node* next; |
- Node* n; |
if (processStart) { |
- for (n = processStart; n && n != processEnd; n = next) { |
- next = n->nextSibling(); |
+ NodeVector nodes; |
+ for (Node* n = processStart; n && n != processEnd; n = n->nextSibling()) |
+ nodes.append(n); |
+ for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) { |
+ Node* n = it->get(); |
if (action == EXTRACT_CONTENTS) |
fragment->appendChild(n, ec); // will remove from commonRoot |
else if (action == CLONE_CONTENTS) |