Commit 65374915 authored by inferno@chromium.org's avatar inferno@chromium.org

2010-12-10 Emil Eklund <eae@chromium.org>

        Reviewed by Adam Barth.

        Fix crash in Range::processContents when modified during mutation event.
        https://bugs.webkit.org/show_bug.cgi?id=50710

        Test: fast/dom/Range/range-extractContents.html

        * dom/Range.cpp:
        (WebCore::Range::processContents):
        Replace raw pointers with RefPtrs and add checks.
2010-12-10  Emil Eklund  <eae@chromium.org>

        Reviewed by Adam Barth.

        Add testcase for range.extractContents crash.
        https://bugs.webkit.org/show_bug.cgi?id=50710

        * fast/dom/Range/range-extractContents-expected.txt: Added.
        * fast/dom/Range/range-extractContents.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73799 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c91e4970
2010-12-10 Emil Eklund <eae@chromium.org>
Reviewed by Adam Barth.
Add testcase for range.extractContents crash.
https://bugs.webkit.org/show_bug.cgi?id=50710
* fast/dom/Range/range-extractContents-expected.txt: Added.
* fast/dom/Range/range-extractContents.html: Added.
2010-12-10 Peter Kasting <pkasting@google.com>
Unreviewed Chromium test expectations update.
......
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function log(msg)
{
document.body.appendChild(document.createTextNode(msg + '\n'));
}
function runTests()
{
if (window.layoutTestController)
layoutTestController.dumpAsText();
document.addEventListener("DOMSubtreeModified", function() {
document.getElementById('cont').innerHTML = '';
}, false);
var r = document.createRange();
try {
r.setStartBefore(document.getElementById('start'));
r.setEndAfter(document.getElementById('end'));
var fragment = r.extractContents();
document.body.appendChild(fragment);
} catch(e) {
}
log('PASS: No crash.');
}
</script>
</head>
<body onload="runTests();">
<p id="cont">
<span>This <span id="start">tests</span></span>
<span>that we don't crash when mutating the dom during</span>
<span>an <code id="end">extractContents</code> call.</span>
</p>
</body>
</html>
2010-12-10 Emil Eklund <eae@chromium.org>
Reviewed by Adam Barth.
Fix crash in Range::processContents when modified during mutation event.
https://bugs.webkit.org/show_bug.cgi?id=50710
Test: fast/dom/Range/range-extractContents.html
* dom/Range.cpp:
(WebCore::Range::processContents):
Replace raw pointers with RefPtrs and add checks.
2010-12-09 Enrica Casucci <enrica@apple.com>
Reviewed by Alexey Proskuryakov.
......
......@@ -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 @@ bool Range::intersectsNode(Node* refNode, ExceptionCode& ec)
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 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
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 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
} 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 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
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 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception
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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment