Commit 66dbeb14 authored by sigbjornf@opera.com's avatar sigbjornf@opera.com

Handle parser-blocking script cancellations while nested.

Gracefully handle cancellation of a parser-blocking script load that
was initiated while already executing scripts. That is, quietly stop
waiting for it to load without notifying the host.

R=marja@chromium.org,kouhei@chromium.org,haraken@chromium.org
BUG=398090

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

git-svn-id: svn://svn.chromium.org/blink/trunk@185122 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent bc379acc
Cancelling a document.write()-inserted and blocking script shouldn't fail.
PASS if no crash.
<!DOCTYPE html>
<p>Cancelling a document.write()-inserted and blocking script shouldn't fail.</p>
<p>PASS if no crash.</p>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.setCanOpenWindows();
testRunner.waitUntilDone();
}
window.open("resources/document-write-then-close.html");
</script>
<!DOCTYPE html>
<script>
document.write("<script src='" + "irrelevant.js" + "'></scr" + "ipt>");
window.close();
if (window.testRunner)
testRunner.notifyDone();
</script>
......@@ -165,8 +165,34 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
ASSERT(!isExecutingScript());
}
void HTMLScriptRunner::stopWatchingResourceForLoad(Resource* resource)
{
if (m_parserBlockingScript.resource() == resource) {
m_parserBlockingScript.stopWatchingForLoad(this);
m_parserBlockingScript.releaseElementAndClear();
return;
}
for (PendingScript& script : m_scriptsToExecuteAfterParsing) {
if (script.resource() == resource) {
script.stopWatchingForLoad(this);
script.releaseElementAndClear();
return;
}
}
}
void HTMLScriptRunner::notifyFinished(Resource* cachedResource)
{
// Handle cancellations of parser-blocking script loads without
// notifying the host (i.e., parser) if these were initiated by nested
// document.write()s. The cancellation may have been triggered by
// script execution to signal an abrupt stop (e.g., window.close().)
//
// The parser is unprepared to be told, and doesn't need to be.
if (isExecutingScript() && cachedResource->wasCanceled()) {
stopWatchingResourceForLoad(cachedResource);
return;
}
m_host->notifyScriptLoaded(cachedResource);
}
......
......@@ -82,6 +82,8 @@ private:
bool isPendingScriptReady(const PendingScript&);
void stopWatchingResourceForLoad(Resource*);
RawPtrWillBeMember<Document> m_document;
RawPtrWillBeMember<HTMLScriptRunnerHost> m_host;
PendingScript m_parserBlockingScript;
......
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