Commit 603b7252 authored by yoichio@chromium.org's avatar yoichio@chromium.org

Postpone mutation event dispatch in Selection.deleteFromDocument.

A crash bug which an attached test case causes is following: 
1. Selection.deleteFromDocument calls Range.deleteContents which removes a node through Node.removeChild. 
2. Node.removeChild calls a DOMNodeRemoved event which removes the node. 
3. Then Node.removeChild asserts a DOM exception NOT_FOUND_ERR. 
4. Range.deleteContents picks the exception and it causes crash because Selection.deleteFromDocument calls Range.deleteContents with ASSERT_NO_EXCEPTION. 

This cl changes Selection.deleteFromDocument to delay the mutation event dispatching when it calls Range.deleteContents.
Especially, DOMNodeRemoved will be not kicked.

BUG=339186

Review URL: https://codereview.chromium.org/199383004

git-svn-id: svn://svn.chromium.org/blink/trunk@174944 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 19e50f84
Should not crash if we load a test case from crbug.com/339186.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS event.data is "FINISH"
PASS Did not crash.
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<head>
<title>Crash issue 339186</title>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<script>
description('Should not crash if we load a test case from crbug.com/339186.');
window.jsTestIsAsync = true;
window.addEventListener('message', didReceiveMessage, false);
var iframe = document.createElement('iframe');
iframe.src = 'resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html';
document.body.appendChild(iframe);
function didReceiveMessage(event)
{
shouldBeEqualToString('event.data', 'FINISH');
document.body.removeChild(iframe);
testPassed('Did not crash.');
window.finishJSTest();
}
</script>
</body>
</html>
<html>
<head>
<script>
var count = 0;
document.addEventListener("DOMNodeRemoved", function () {
count++;
if (count < 2) {
var src = event.srcElement;
document.designMode = "on";
src.parentNode.replaceChild(document.head, src);
}
}, false);
window.onload = function () {
var selection = window.getSelection();
document.execCommand("SelectAll", false)
selection.deleteFromDocument();
window.parent.postMessage("FINISH", "*");
};
</script>
</head>
<body>
<div>
A
<select></select>
</div>
</body>
</html>
......@@ -34,12 +34,12 @@
#include "core/dom/NodeTraversal.h"
#include "core/dom/NodeWithIndex.h"
#include "core/dom/ProcessingInstruction.h"
#include "core/events/ScopedEventQueue.h"
#include "core/dom/Text.h"
#include "core/editing/TextIterator.h"
#include "core/editing/VisiblePosition.h"
#include "core/editing/VisibleUnits.h"
#include "core/editing/markup.h"
#include "core/events/ScopedEventQueue.h"
#include "core/html/HTMLElement.h"
#include "core/rendering/RenderBoxModelObject.h"
#include "core/rendering/RenderText.h"
......@@ -470,7 +470,10 @@ void Range::deleteContents(ExceptionState& exceptionState)
if (exceptionState.hadException())
return;
processContents(DELETE_CONTENTS, exceptionState);
{
EventQueueScope eventQueueScope;
processContents(DELETE_CONTENTS, exceptionState);
}
}
bool Range::intersectsNode(Node* refNode, ExceptionState& exceptionState)
......
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