summaryrefslogtreecommitdiffstats
path: root/WebCore/html/parser/HTMLScriptRunner.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/html/parser/HTMLScriptRunner.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/html/parser/HTMLScriptRunner.cpp')
-rw-r--r--WebCore/html/parser/HTMLScriptRunner.cpp318
1 files changed, 0 insertions, 318 deletions
diff --git a/WebCore/html/parser/HTMLScriptRunner.cpp b/WebCore/html/parser/HTMLScriptRunner.cpp
deleted file mode 100644
index 7978a0f..0000000
--- a/WebCore/html/parser/HTMLScriptRunner.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "HTMLScriptRunner.h"
-
-#include "Attribute.h"
-#include "CachedScript.h"
-#include "CachedResourceLoader.h"
-#include "Element.h"
-#include "Event.h"
-#include "Frame.h"
-#include "HTMLInputStream.h"
-#include "HTMLNames.h"
-#include "HTMLScriptRunnerHost.h"
-#include "IgnoreDestructiveWriteCountIncrementer.h"
-#include "NestingLevelIncrementer.h"
-#include "NotImplemented.h"
-#include "ScriptElement.h"
-#include "ScriptSourceCode.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-HTMLScriptRunner::HTMLScriptRunner(Document* document, HTMLScriptRunnerHost* host)
- : m_document(document)
- , m_host(host)
- , m_scriptNestingLevel(0)
- , m_hasScriptsWaitingForStylesheets(false)
-{
- ASSERT(m_host);
-}
-
-HTMLScriptRunner::~HTMLScriptRunner()
-{
- // FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction?
- if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
- stopWatchingForLoad(m_parsingBlockingScript);
-
- while (!m_scriptsToExecuteAfterParsing.isEmpty()) {
- PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst();
- if (pendingScript.cachedScript() && pendingScript.watchingForLoad())
- stopWatchingForLoad(pendingScript);
- }
-}
-
-void HTMLScriptRunner::detach()
-{
- m_document = 0;
-}
-
-static KURL documentURLForScriptExecution(Document* document)
-{
- if (!document || !document->frame())
- return KURL();
-
- // Use the URL of the currently active document for this frame.
- return document->frame()->document()->url();
-}
-
-inline PassRefPtr<Event> createScriptLoadEvent()
-{
- return Event::create(eventNames().loadEvent, false, false);
-}
-
-inline PassRefPtr<Event> createScriptErrorEvent()
-{
- return Event::create(eventNames().errorEvent, true, false);
-}
-
-ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript& script, bool& errorOccurred) const
-{
- if (script.cachedScript()) {
- errorOccurred = script.cachedScript()->errorOccurred();
- ASSERT(script.cachedScript()->isLoaded());
- return ScriptSourceCode(script.cachedScript());
- }
- errorOccurred = false;
- return ScriptSourceCode(script.element()->textContent(), documentURLForScriptExecution(m_document), script.startingPosition());
-}
-
-bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
-{
- m_hasScriptsWaitingForStylesheets = !m_document->haveStylesheetsLoaded();
- if (m_hasScriptsWaitingForStylesheets)
- return false;
- if (script.cachedScript() && !script.cachedScript()->isLoaded())
- return false;
- return true;
-}
-
-void HTMLScriptRunner::executeParsingBlockingScript()
-{
- ASSERT(m_document);
- ASSERT(!m_scriptNestingLevel);
- ASSERT(m_document->haveStylesheetsLoaded());
- ASSERT(isPendingScriptReady(m_parsingBlockingScript));
-
- InsertionPointRecord insertionPointRecord(m_host->inputStream());
- executePendingScriptAndDispatchEvent(m_parsingBlockingScript);
-}
-
-void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
-{
- bool errorOccurred = false;
- ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred);
-
- // Stop watching loads before executeScript to prevent recursion if the script reloads itself.
- if (pendingScript.cachedScript() && pendingScript.watchingForLoad())
- stopWatchingForLoad(pendingScript);
-
- // Clear the pending script before possible rentrancy from executeScript()
- RefPtr<Element> element = pendingScript.releaseElementAndClear();
- if (ScriptElement* scriptElement = toScriptElement(element.get())) {
- NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
- IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(m_document);
- if (errorOccurred)
- element->dispatchEvent(createScriptErrorEvent());
- else {
- ASSERT(isExecutingScript());
- scriptElement->executeScript(sourceCode);
- element->dispatchEvent(createScriptLoadEvent());
- }
- }
- ASSERT(!m_scriptNestingLevel);
-}
-
-void HTMLScriptRunner::watchForLoad(PendingScript& pendingScript)
-{
- ASSERT(!pendingScript.watchingForLoad());
- m_host->watchForLoad(pendingScript.cachedScript());
- pendingScript.setWatchingForLoad(true);
-}
-
-void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
-{
- ASSERT(pendingScript.watchingForLoad());
- m_host->stopWatchingForLoad(pendingScript.cachedScript());
- 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.
-bool HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosition1& scriptStartPosition)
-{
- ASSERT(scriptElement);
- // FIXME: If scripting is disabled, always just return true;
-
- // Try to execute the script given to us.
- runScript(scriptElement.get(), scriptStartPosition);
-
- if (haveParsingBlockingScript()) {
- if (m_scriptNestingLevel)
- return false; // Block the parser. Unwind to the outermost HTMLScriptRunner::execute before continuing parsing.
- if (!executeParsingBlockingScripts())
- return false; // We still have a parsing blocking script, block the parser.
- }
- return true; // Scripts executed as expected, continue parsing.
-}
-
-bool HTMLScriptRunner::haveParsingBlockingScript() const
-{
- return !!m_parsingBlockingScript.element();
-}
-
-bool HTMLScriptRunner::executeParsingBlockingScripts()
-{
- while (haveParsingBlockingScript()) {
- // We only really need to check once.
- if (!isPendingScriptReady(m_parsingBlockingScript))
- return false;
- executeParsingBlockingScript();
- }
- return true;
-}
-
-bool HTMLScriptRunner::executeScriptsWaitingForLoad(CachedResource* cachedScript)
-{
- ASSERT(!m_scriptNestingLevel);
- ASSERT(haveParsingBlockingScript());
- ASSERT_UNUSED(cachedScript, m_parsingBlockingScript.cachedScript() == cachedScript);
- ASSERT(m_parsingBlockingScript.cachedScript()->isLoaded());
- return executeParsingBlockingScripts();
-}
-
-bool HTMLScriptRunner::executeScriptsWaitingForStylesheets()
-{
- ASSERT(m_document);
- // Callers should check hasScriptsWaitingForStylesheets() before calling
- // to prevent parser or script re-entry during </style> parsing.
- ASSERT(hasScriptsWaitingForStylesheets());
- ASSERT(!m_scriptNestingLevel);
- ASSERT(m_document->haveStylesheetsLoaded());
- return executeParsingBlockingScripts();
-}
-
-bool HTMLScriptRunner::executeScriptsWaitingForParsing()
-{
- while (!m_scriptsToExecuteAfterParsing.isEmpty()) {
- ASSERT(!m_scriptNestingLevel);
- ASSERT(!haveParsingBlockingScript());
- ASSERT(m_scriptsToExecuteAfterParsing.first().cachedScript());
- if (!m_scriptsToExecuteAfterParsing.first().cachedScript()->isLoaded()) {
- watchForLoad(m_scriptsToExecuteAfterParsing.first());
- return false;
- }
- PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst();
- executePendingScriptAndDispatchEvent(first);
- if (!m_document)
- return false;
- }
- return true;
-}
-
-void HTMLScriptRunner::requestParsingBlockingScript(Element* element)
-{
- 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);
-}
-
-void HTMLScriptRunner::requestDeferredScript(Element* element)
-{
- PendingScript pendingScript;
- if (!requestPendingScript(pendingScript, element))
- return;
-
- ASSERT(pendingScript.cachedScript());
- m_scriptsToExecuteAfterParsing.append(pendingScript);
-}
-
-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 false;
- // FIXME: We need to resolve the url relative to the element.
- if (!script->dispatchBeforeLoadEvent(srcValue))
- return false;
- pendingScript.adoptElement(script);
- // This should correctly return 0 for empty or invalid srcValues.
- CachedScript* cachedScript = m_document->cachedResourceLoader()->requestScript(srcValue, toScriptElement(script)->scriptCharset());
- if (!cachedScript) {
- notImplemented(); // Dispatch error event.
- return false;
- }
- pendingScript.setCachedScript(cachedScript);
- 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
-void HTMLScriptRunner::runScript(Element* script, const TextPosition1& scriptStartPosition)
-{
- ASSERT(m_document);
- ASSERT(!haveParsingBlockingScript());
- {
- InsertionPointRecord insertionPointRecord(m_host->inputStream());
- NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
-
- ScriptElement* scriptElement = toScriptElement(script);
- ASSERT(scriptElement);
- if (!scriptElement->shouldExecuteAsJavaScript())
- return;
-
- if (script->hasAttribute(srcAttr)) {
- if (script->hasAttribute(asyncAttr)) // Async takes precendence over defer.
- return; // Asynchronous scripts handle themselves.
-
- if (script->hasAttribute(deferAttr))
- requestDeferredScript(script);
- else
- requestParsingBlockingScript(script);
- } else {
- // FIXME: We do not block inline <script> tags on stylesheets to match the
- // 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), scriptStartPosition);
- scriptElement->executeScript(sourceCode);
- }
- }
-}
-
-}