Commit 9e4a1523 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

MutationObserver: Do nothing when its execution context is no longer available.

MutationObserver::DeliverMutations is a static function and
registered to the microtask queue.  It maintains active
observers and also makes active observers alive, but nothing
else (the underlying callback function nor execution context).

So, when DeliverMutations invokes each active observer,
DeliverMutations must make sure that each active observer's
execution context is still available.

This patch adds the check of the execution context.

Bug: 788495, 789862
Change-Id: Ic350603cc8a7b13275adf042e731fdd9605373aa
Reviewed-on: https://chromium-review.googlesource.com/799653
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520509}
parent ac05e5b2
<!-- https://crbug.com/788495 -->
<div id="observation-target">This test passes if it does not crash.</div>
<iframe id="child-frame" src="#load-the-same-document-page"></iframe>
<script>
if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.dumpAsText();
}
var mutationObserver;
let childFrame = document.getElementById('child-frame');
document.addEventListener('DOMContentLoaded', onContentLoaded, false);
function onContentLoaded() {
mutationObserver = new MutationObserver(() => {});
mutationObserver.observe(document.getElementById('observation-target'),
{attributes: true});
setTimeout(attemptToCauseCrash, /* Needs enough time */ 100);
}
function attemptToCauseCrash() {
doc1 = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html');
doc1.adoptNode(childFrame.contentDocument.documentElement);
doc2 = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html');
doc2.documentElement.appendChild(childFrame);
doc2.documentElement.parentNode.removeChild(doc2.documentElement);
gc();
setTimeout(() => testRunner.notifyDone(), 0);
}
</script>
...@@ -355,6 +355,12 @@ void MutationObserver::DeliverMutations() { ...@@ -355,6 +355,12 @@ void MutationObserver::DeliverMutations() {
std::sort(observers.begin(), observers.end(), ObserverLessThan()); std::sort(observers.begin(), observers.end(), ObserverLessThan());
for (const auto& observer : observers) { for (const auto& observer : observers) {
if (!observer->GetExecutionContext()) {
// The observer's execution context is already gone, as active observers
// intentionally do not hold their execution context. Do nothing then.
continue;
}
if (observer->ShouldBeSuspended()) if (observer->ShouldBeSuspended())
SuspendedMutationObservers().insert(observer); SuspendedMutationObservers().insert(observer);
else else
......
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