summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp101
1 files changed, 71 insertions, 30 deletions
diff --git a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
index 1cb6555c243..70c4c25f3b5 100644
--- a/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
+++ b/chromium/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
@@ -33,10 +33,10 @@
#include "core/dom/Microtask.h"
#include "core/dom/ScriptLoader.h"
#include "core/fetch/ScriptResource.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/parser/HTMLInputStream.h"
#include "core/html/parser/HTMLScriptRunnerHost.h"
#include "core/html/parser/NestingLevelIncrementer.h"
-#include "core/frame/Frame.h"
#include "platform/NotImplemented.h"
namespace WebCore {
@@ -54,7 +54,23 @@ HTMLScriptRunner::HTMLScriptRunner(Document* document, HTMLScriptRunnerHost* hos
HTMLScriptRunner::~HTMLScriptRunner()
{
- // FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction?
+#if ENABLE(OILPAN)
+ // If the document is destructed without having explicitly
+ // detached the parser (and this script runner object), perform
+ // detach steps now. This will happen if the Document, the parser
+ // and this script runner object are swept out in the same GC.
+ detach();
+#else
+ // Verify that detach() has been called.
+ ASSERT(!m_document);
+#endif
+}
+
+void HTMLScriptRunner::detach()
+{
+ if (!m_document)
+ return;
+
if (m_parserBlockingScript.resource() && m_parserBlockingScript.watchingForLoad())
stopWatchingForLoad(m_parserBlockingScript);
@@ -63,23 +79,25 @@ HTMLScriptRunner::~HTMLScriptRunner()
if (pendingScript.resource() && pendingScript.watchingForLoad())
stopWatchingForLoad(pendingScript);
}
-}
-
-void HTMLScriptRunner::detach()
-{
- m_document = 0;
+ m_document = nullptr;
}
static KURL documentURLForScriptExecution(Document* document)
{
- if (!document || !document->frame())
+ if (!document)
+ return KURL();
+
+ if (!document->frame()) {
+ if (document->importsController())
+ return document->url();
return KURL();
+ }
// Use the URL of the currently active document for this frame.
return document->frame()->document()->url();
}
-inline PassRefPtr<Event> createScriptLoadEvent()
+inline PassRefPtrWillBeRawPtr<Event> createScriptLoadEvent()
{
return Event::create(EventTypeNames::load);
}
@@ -97,7 +115,7 @@ ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript&
bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
{
- m_hasScriptsWaitingForResources = !m_document->haveStylesheetsAndImportsLoaded();
+ m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady();
if (m_hasScriptsWaitingForResources)
return false;
if (script.resource() && !script.resource()->isLoaded())
@@ -109,14 +127,14 @@ void HTMLScriptRunner::executeParsingBlockingScript()
{
ASSERT(m_document);
ASSERT(!isExecutingScript());
- ASSERT(m_document->haveStylesheetsAndImportsLoaded());
+ ASSERT(m_document->isScriptExecutionReady());
ASSERT(isPendingScriptReady(m_parserBlockingScript));
InsertionPointRecord insertionPointRecord(m_host->inputStream());
- executePendingScriptAndDispatchEvent(m_parserBlockingScript);
+ executePendingScriptAndDispatchEvent(m_parserBlockingScript, PendingScriptBlockingParser);
}
-void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
+void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript, PendingScriptType pendingScriptType)
{
bool errorOccurred = false;
ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);
@@ -125,11 +143,18 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
if (pendingScript.resource() && pendingScript.watchingForLoad())
stopWatchingForLoad(pendingScript);
- if (!isExecutingScript())
+ if (!isExecutingScript()) {
Microtask::performCheckpoint();
+ if (pendingScriptType == PendingScriptBlockingParser) {
+ m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady();
+ // The parser cannot be unblocked as a microtask requested another resource
+ if (m_hasScriptsWaitingForResources)
+ return;
+ }
+ }
// Clear the pending script before possible rentrancy from executeScript()
- RefPtr<Element> element = pendingScript.releaseElementAndClear();
+ RefPtrWillBeRawPtr<Element> element = pendingScript.releaseElementAndClear();
if (ScriptLoader* scriptLoader = toScriptLoaderIfPossible(element.get())) {
NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document);
@@ -137,8 +162,8 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
scriptLoader->dispatchErrorEvent();
else {
ASSERT(isExecutingScript());
- if (scriptLoader->executePotentiallyCrossOriginScript(sourceCode))
- element->dispatchEvent(createScriptLoadEvent());
+ scriptLoader->executeScript(sourceCode);
+ element->dispatchEvent(createScriptLoadEvent());
}
}
ASSERT(!isExecutingScript());
@@ -147,20 +172,30 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
void HTMLScriptRunner::watchForLoad(PendingScript& pendingScript)
{
ASSERT(!pendingScript.watchingForLoad());
- m_host->watchForLoad(pendingScript.resource());
+ ASSERT(!pendingScript.resource()->isLoaded());
+ // addClient() will call notifyFinished() if the load is complete.
+ // Callers do not expect to be re-entered from this call, so they
+ // should not become a client of an already-loaded Resource.
+ pendingScript.resource()->addClient(this);
pendingScript.setWatchingForLoad(true);
}
void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
{
ASSERT(pendingScript.watchingForLoad());
- m_host->stopWatchingForLoad(pendingScript.resource());
+ pendingScript.resource()->removeClient(this);
pendingScript.setWatchingForLoad(false);
}
-// This function should match 10.2.5.11 "An end tag whose tag name is 'script'"
-// Script handling lives outside the tree builder to keep the each class simple.
-void HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosition& scriptStartPosition)
+void HTMLScriptRunner::notifyFinished(Resource* cachedResource)
+{
+ m_host->notifyScriptLoaded(cachedResource);
+}
+
+// Implements the steps for 'An end tag whose tag name is "script"'
+// http://whatwg.org/html#scriptEndTag
+// Script handling lives outside the tree builder to keep each class simple.
+void HTMLScriptRunner::execute(PassRefPtrWillBeRawPtr<Element> scriptElement, const TextPosition& scriptStartPosition)
{
ASSERT(scriptElement);
// FIXME: If scripting is disabled, always just return.
@@ -207,7 +242,7 @@ void HTMLScriptRunner::executeScriptsWaitingForResources()
// to prevent parser or script re-entry during </style> parsing.
ASSERT(hasScriptsWaitingForResources());
ASSERT(!isExecutingScript());
- ASSERT(m_document->haveStylesheetsAndImportsLoaded());
+ ASSERT(m_document->isScriptExecutionReady());
executeParsingBlockingScripts();
}
@@ -222,7 +257,7 @@ bool HTMLScriptRunner::executeScriptsWaitingForParsing()
return false;
}
PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst();
- executePendingScriptAndDispatchEvent(first);
+ executePendingScriptAndDispatchEvent(first, PendingScriptDeferred);
// FIXME: What is this m_document check for?
if (!m_document)
return false;
@@ -268,8 +303,8 @@ bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Elemen
return true;
}
-// This method is meant to match the HTML5 definition of "running a script"
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#running-a-script
+// Implements the initial steps for 'An end tag whose tag name is "script"'
+// http://whatwg.org/html#scriptEndTag
void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStartPosition)
{
ASSERT(m_document);
@@ -285,10 +320,8 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStar
if (!scriptLoader)
return;
- // FIXME: This may be too agressive as we always deliver mutations at
- // every script element, even if it's not ready to execute yet. There's
- // unfortuantely no obvious way to tell if prepareScript is going to
- // execute the script from out here.
+ ASSERT(scriptLoader->isParserInserted());
+
if (!isExecutingScript())
Microtask::performCheckpoint();
@@ -316,4 +349,12 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStar
}
}
+void HTMLScriptRunner::trace(Visitor* visitor)
+{
+ visitor->trace(m_document);
+ visitor->trace(m_host);
+ visitor->trace(m_parserBlockingScript);
+ visitor->trace(m_scriptsToExecuteAfterParsing);
+}
+
}