Commit fd7d08f7 authored by tonyg@chromium.org's avatar tonyg@chromium.org

2010-08-13 Tony Gentilcore <tonyg@chromium.org>

        Reviewed by Eric Seidel.

        Refactor HTMLScriptRunner to allow deferred scripts to share code
        https://bugs.webkit.org/show_bug.cgi?id=43736

        No new tests because no functional change

        * html/HTMLScriptRunner.cpp:
        (WebCore::HTMLScriptRunner::sourceFromPendingScript): Make const to enforce the idea that it doesn't change m_parsingBlockingScript.
        (WebCore::HTMLScriptRunner::executeParsingBlockingScript): Rename to make it clear this deals with the parsing blocking script and refactor to use executePendingScriptAndDispatchEvent.
        (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent): Factored out of executePendingScript, this can be used for executing any external script.
        (WebCore::HTMLScriptRunner::executeScript): This can be used for executing any inline or external script. ASSERTs moved to the two calling points.
        (WebCore::HTMLScriptRunner::executeParsingBlockingScripts): Moved method.
        (WebCore::HTMLScriptRunner::requestParsingBlockingScript): Factored out requestPendingScript.
        (WebCore::HTMLScriptRunner::requestPendingScript): Factored out from reqeustParsingBlockingScript.
        (WebCore::HTMLScriptRunner::runScript):
        * html/HTMLScriptRunner.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65350 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent bc0c4c2a
2010-08-13 Tony Gentilcore <tonyg@chromium.org>
Reviewed by Eric Seidel.
Refactor HTMLScriptRunner to allow deferred scripts to share code
https://bugs.webkit.org/show_bug.cgi?id=43736
No new tests because no functional change
* html/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::sourceFromPendingScript): Make const to enforce the idea that it doesn't change m_parsingBlockingScript.
(WebCore::HTMLScriptRunner::executeParsingBlockingScript): Rename to make it clear this deals with the parsing blocking script and refactor to use executePendingScriptAndDispatchEvent.
(WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent): Factored out of executePendingScript, this can be used for executing any external script.
(WebCore::HTMLScriptRunner::executeScript): This can be used for executing any inline or external script. ASSERTs moved to the two calling points.
(WebCore::HTMLScriptRunner::executeParsingBlockingScripts): Moved method.
(WebCore::HTMLScriptRunner::requestParsingBlockingScript): Factored out requestPendingScript.
(WebCore::HTMLScriptRunner::requestPendingScript): Factored out from reqeustParsingBlockingScript.
(WebCore::HTMLScriptRunner::runScript):
* html/HTMLScriptRunner.h:
2010-08-13 Gavin Barraclough <barraclough@apple.com>
Windows build fix.
......@@ -43,23 +43,22 @@ namespace WebCore {
using namespace HTMLNames;
class NestScript : public Noncopyable {
// FIXME: Factor out to avoid duplication with HTMLDocumentParser.
class NestingLevelIncrementer : public Noncopyable {
public:
NestScript(unsigned& nestingLevel, HTMLInputStream& inputStream)
explicit NestingLevelIncrementer(unsigned& nestingLevel)
: m_nestingLevel(&nestingLevel)
, m_savedInsertionPoint(inputStream)
{
++(*m_nestingLevel);
}
~NestScript()
~NestingLevelIncrementer()
{
--(*m_nestingLevel);
}
private:
unsigned* m_nestingLevel;
InsertionPointRecord m_savedInsertionPoint;
};
HTMLScriptRunner::HTMLScriptRunner(Document* document, HTMLScriptRunnerHost* host)
......@@ -97,7 +96,7 @@ inline PassRefPtr<Event> createScriptErrorEvent()
return Event::create(eventNames().errorEvent, true, false);
}
ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript& script, bool& errorOccurred)
ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript& script, bool& errorOccurred) const
{
if (script.cachedScript()) {
errorOccurred = script.cachedScript()->errorOccurred();
......@@ -118,22 +117,29 @@ bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
return true;
}
void HTMLScriptRunner::executePendingScript()
void HTMLScriptRunner::executeParsingBlockingScript()
{
ASSERT(!m_scriptNestingLevel);
ASSERT(m_document->haveStylesheetsLoaded());
bool errorOccurred = false;
ASSERT(isPendingScriptReady(m_parsingBlockingScript));
ScriptSourceCode sourceCode = sourceFromPendingScript(m_parsingBlockingScript, errorOccurred);
// Stop watching loads before executeScript to prevent recursion if the script reloads itself.
if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
stopWatchingForLoad(m_parsingBlockingScript);
InsertionPointRecord insertionPointRecord(m_host->inputStream());
executePendingScriptAndDispatchEvent(m_parsingBlockingScript);
}
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
{
bool errorOccurred = false;
ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);
// Clear the pending script before possible rentrancy from executeScript()
RefPtr<Element> scriptElement = m_parsingBlockingScript.releaseElementAndClear();
RefPtr<Element> scriptElement = pendingScript.releaseElementAndClear();
{
NestScript nestingLevel(m_scriptNestingLevel, m_host->inputStream());
NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
if (errorOccurred)
scriptElement->dispatchEvent(createScriptErrorEvent());
else {
......@@ -144,12 +150,8 @@ void HTMLScriptRunner::executePendingScript()
ASSERT(!m_scriptNestingLevel);
}
void HTMLScriptRunner::executeScript(Element* element, const ScriptSourceCode& sourceCode)
void HTMLScriptRunner::executeScript(Element* element, const ScriptSourceCode& sourceCode) const
{
// FIXME: We do not block inline <script> tags on stylesheets for now.
// When we do, || !element->hasAttribute(srcAttr) should be removed from
// the ASSERT below. See https://bugs.webkit.org/show_bug.cgi?id=40047
ASSERT(m_document->haveStylesheetsLoaded() || !element->hasAttribute(srcAttr));
ScriptElement* scriptElement = toScriptElement(element);
ASSERT(scriptElement);
if (!scriptElement->shouldExecuteAsJavaScript())
......@@ -204,7 +206,7 @@ bool HTMLScriptRunner::executeParsingBlockingScripts()
// We only really need to check once.
if (!isPendingScriptReady(m_parsingBlockingScript))
return false;
executePendingScript();
executeParsingBlockingScript();
}
return true;
}
......@@ -228,31 +230,39 @@ bool HTMLScriptRunner::executeScriptsWaitingForStylesheets()
return executeParsingBlockingScripts();
}
void HTMLScriptRunner::requestScript(Element* script)
void HTMLScriptRunner::requestParsingBlockingScript(Element* element)
{
ASSERT(!m_parsingBlockingScript.element());
AtomicString srcValue = script->getAttribute(srcAttr);
if (!requestPendingScript(m_parsingBlockingScript, element))
return;
ASSERT(m_parsingBlockingScript.cachedScript());
// We only care about a load callback if cachedScript is not already
// in the cache. Callers will attempt to run the m_parsingBlockingScript
// if possible before returning control to the parser.
if (!m_parsingBlockingScript.cachedScript()->isLoaded())
watchForLoad(m_parsingBlockingScript);
}
bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const
{
ASSERT(!pendingScript.element());
const AtomicString& srcValue = script->getAttribute(srcAttr);
// Allow the host to disllow script loads (using the XSSAuditor, etc.)
if (!m_host->shouldLoadExternalScriptFromSrc(srcValue))
return;
return false;
// FIXME: We need to resolve the url relative to the element.
if (!script->dispatchBeforeLoadEvent(srcValue))
return;
m_parsingBlockingScript.adoptElement(script);
return false;
pendingScript.adoptElement(script);
// This should correctly return 0 for empty or invalid srcValues.
CachedScript* cachedScript = m_document->docLoader()->requestScript(srcValue, toScriptElement(script)->scriptCharset());
if (!cachedScript) {
notImplemented(); // Dispatch error event.
return;
return false;
}
m_parsingBlockingScript.setCachedScript(cachedScript);
// We only care about a load callback if cachedScript is not already
// in the cache. Callers will attempt to run the m_parsingBlockingScript
// if possible before returning control to the parser.
if (!m_parsingBlockingScript.cachedScript()->isLoaded())
watchForLoad(m_parsingBlockingScript);
pendingScript.setCachedScript(cachedScript);
return true;
}
// This method is meant to match the HTML5 definition of "running a script"
......@@ -261,17 +271,21 @@ void HTMLScriptRunner::runScript(Element* script, int startingLineNumber)
{
ASSERT(!haveParsingBlockingScript());
{
NestScript nestingLevel(m_scriptNestingLevel, m_host->inputStream());
InsertionPointRecord insertionPointRecord(m_host->inputStream());
NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
// Check script type and language, current code uses ScriptElement::shouldExecuteAsJavaScript(), but that may not be HTML5 compliant.
notImplemented(); // event for support
if (script->hasAttribute(srcAttr)) {
// FIXME: Handle defer and async
requestScript(script);
requestParsingBlockingScript(script);
} else {
// FIXME: We do not block inline <script> tags on stylesheets to match the
// old parser for now. See https://bugs.webkit.org/show_bug.cgi?id=40047
// old parser for now. When we do, the ASSERT below should be added.
// See https://bugs.webkit.org/show_bug.cgi?id=40047
// ASSERT(document()->haveStylesheetsLoaded());
ASSERT(isExecutingScript());
ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), startingLineNumber);
executeScript(script, sourceCode);
}
......
......@@ -52,25 +52,27 @@ public:
bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; }
bool executeScriptsWaitingForStylesheets();
bool isExecutingScript() { return !!m_scriptNestingLevel; }
bool isExecutingScript() const { return !!m_scriptNestingLevel; }
private:
Frame* frame() const;
void executeParsingBlockingScript();
void executePendingScriptAndDispatchEvent(PendingScript&);
void executeScript(Element*, const ScriptSourceCode&) const;
bool haveParsingBlockingScript() const;
bool executeParsingBlockingScripts();
void executePendingScript();
void requestScript(Element*);
void requestParsingBlockingScript(Element*);
bool requestPendingScript(PendingScript&, Element*) const;
void runScript(Element*, int startingLineNumber);
// Helpers for dealing with HTMLScriptRunnerHost
void watchForLoad(PendingScript&);
void stopWatchingForLoad(PendingScript&);
void executeScript(Element*, const ScriptSourceCode&);
bool isPendingScriptReady(const PendingScript&);
ScriptSourceCode sourceFromPendingScript(const PendingScript&, bool& errorOccurred);
ScriptSourceCode sourceFromPendingScript(const PendingScript&, bool& errorOccurred) const;
Document* m_document;
HTMLScriptRunnerHost* m_host;
......
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