Commit 48227c77 authored by yosin@chromium.org's avatar yosin@chromium.org

Don't call Document::nodeWillRemoved() with a node in different document

This patch changes |ContainerNode::willRemoveChild()| not to call
|Document::nodeWillRemoved()| for a node in different document since we
assume |Document::nodeWillRemoved()| will be called for owner document.

This situation can be happened when DOM mutation event handler moves
a removing node to another document via |dispatchChildRemovalEvents()| call in
|ContainerNode::willRemoveChild()| at L439.

BUG=477584
TEST=LayoutTests/fast/dom/Range/range-dom-node-removed-assert.html

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

git-svn-id: svn://svn.chromium.org/blink/trunk@200791 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 7cc149e8
<!DOCTYPE html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<div id="sample"></div>
<div id="log"></div>
<script>
var moved = false;
var sample = document.getElementById('sample');
var range = document.createRange();
range.setStart(sample, 0);
range.setEnd(sample, 0);
sample.addEventListener('DOMNodeRemoved', function() {
if (moved)
return;
moved = true;
document.implementation.createDocument('', null).appendChild(sample);
});
test(function() {
var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html');
try {
doc.documentElement.appendChild(sample);
} catch (exception) {
assert_equals(exception.toString(), 'NotFoundError: Failed to execute \'appendChild\' on \'Node\': The node to be removed is no longer a child of this node. Perhaps it was moved in response to a mutation?');
}
});
</script>
......@@ -438,12 +438,18 @@ void ContainerNode::willRemoveChild(Node& child)
child.notifyMutationObserversNodeWillDetach();
dispatchChildRemovalEvents(child);
ChildFrameDisconnector(child).disconnect();
if (document() != child.document()) {
// |child| was moved another document by DOM mutation event handler.
return;
}
// nodeWillBeRemoved must be run after ChildFrameDisconnector, because ChildFrameDisconnector can run script
// which may cause state that is to be invalidated by removing the node.
// |nodeWillBeRemoved()| must be run after |ChildFrameDisconnector|, because
// |ChildFrameDisconnector| can run script which may cause state that is to
// be invalidated by removing the node.
ScriptForbiddenScope scriptForbiddenScope;
EventDispatchForbiddenScope assertNoEventDispatch;
document().nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
// e.g. mutation event listener can create a new range.
document().nodeWillBeRemoved(child);
}
void ContainerNode::willRemoveChildren()
......
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