| 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)
|
|
|