2011-03-15 James Simonsen <simonjam@chromium.org>
Reviewed by Tony Gentilcore.
Need different behavior for ensuring execution order of dynamically loaded scripts
https://bugs.webkit.org/show_bug.cgi?id=50115
Dynamically added scripts with async=false will load in parallel, but execute in order.
See: http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#force-async
* fast/dom/HTMLScriptElement/script-async-attr-expected.txt: Added test cases for forceAsync.
* fast/dom/HTMLScriptElement/script-async-attr.html: Ditto.
* http/tests/misc/script-async-load-execute-in-order-expected.txt: Added.
* http/tests/misc/script-async-load-execute-in-order.html: Added.
2011-03-15 James Simonsen <simonjam@chromium.org>
Reviewed by Tony Gentilcore.
Need different behavior for ensuring execution order of dynamically loaded scripts
https://bugs.webkit.org/show_bug.cgi?id=50115
Dynamically added scripts with async=false will load in parallel, but execute in order.
See: http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#force-async
Tests: fast/dom/HTMLScriptElement/script-async-attr.html
http/tests/misc/script-async-load-execute-in-order.html
* Android.mk: Rename AsyncScriptRunner -> ScriptRunner.
* CMakeLists.txt: Ditto.
* GNUmakefile.am: Ditto.
* WebCore.gypi: Ditto.
* WebCore.pro: Ditto.
* WebCore.vcproj/WebCore.vcproj: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* dom/DOMAllInOne.cpp: Ditto.
* dom/Document.cpp:
(WebCore::Document::Document): Ditto.
(WebCore::Document::~Document): Ditto.
* dom/Document.h:
(WebCore::Document::scriptRunner): Ditto.
* dom/ScriptElement.cpp:
(WebCore::ScriptElement::ScriptElement): Added forceAsync and willExecuteInOrder.
(WebCore::ScriptElement::handleAsyncAttribute): Called by HTMLScriptElement when async attribute changes.
(WebCore::ScriptElement::prepareScript): Added support for forceAsync.
(WebCore::ScriptElement::notifyFinished): Tell ScriptRunner to execute in order if needed.
* dom/ScriptElement.h:
(WebCore::ScriptElement::forceAsync): Added.
* dom/ScriptRunner.cpp: Renamed from Source/WebCore/dom/AsyncScriptRunner.cpp.
(WebCore::ScriptRunner::ScriptRunner): Added in-order script queue.
(WebCore::ScriptRunner::~ScriptRunner): Ditto.
(WebCore::ScriptRunner::executeScriptSoon):
(WebCore::ScriptRunner::queueScriptForInOrderExecution): Added.
(WebCore::ScriptRunner::suspend):
(WebCore::ScriptRunner::resume):
(WebCore::ScriptRunner::timerFired): Execute in-order scripts if ready.
* dom/ScriptRunner.h: Renamed from Source/WebCore/dom/AsyncScriptRunner.h.
(WebCore::ScriptRunner::create):
(WebCore::ScriptRunner::hasPendingScripts): Check for in-order scripts too.
* html/HTMLScriptElement.cpp:
(WebCore::HTMLScriptElement::attributeChanged): Notify ScriptElement when async changes.
(WebCore::HTMLScriptElement::setAsync): Ditto.
(WebCore::HTMLScriptElement::async): Include forceAsync in calculation.
* html/HTMLScriptElement.h:
* html/HTMLScriptElement.idl: Removed Reflect from async for custom behavior.
* page/PageGroupLoadDeferrer.cpp:
(WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer): Rename AsyncScriptRunner -> ScriptRunner.
(WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer): Ditto.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@81198 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/dom/ScriptElement.cpp b/Source/WebCore/dom/ScriptElement.cpp
index 3bba9a0..b4d3670 100644
--- a/Source/WebCore/dom/ScriptElement.cpp
+++ b/Source/WebCore/dom/ScriptElement.cpp
@@ -24,7 +24,6 @@
#include "config.h"
#include "ScriptElement.h"
-#include "AsyncScriptRunner.h"
#include "CachedScript.h"
#include "CachedResourceLoader.h"
#include "Document.h"
@@ -37,6 +36,7 @@
#include "MIMETypeRegistry.h"
#include "Page.h"
#include "ScriptController.h"
+#include "ScriptRunner.h"
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "Settings.h"
@@ -61,6 +61,8 @@
, m_willBeParserExecuted(false)
, m_readyToBeParserExecuted(false)
, m_willExecuteWhenDocumentFinishedParsing(false)
+ , m_forceAsync(!parserInserted)
+ , m_willExecuteInOrder(false)
{
ASSERT(m_element);
}
@@ -96,6 +98,11 @@
prepareScript(); // FIXME: Provide a real starting line number here.
}
+void ScriptElement::handleAsyncAttribute()
+{
+ m_forceAsync = false;
+}
+
// Helper function
static bool isLegacySupportedJavaScriptLanguage(const String& language)
{
@@ -159,7 +166,8 @@
} else
wasParserInserted = false;
- // FIXME: HTML5 spec says we should set forceAsync.
+ if (wasParserInserted && !asyncAttributeValue())
+ m_forceAsync = true;
// FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
if (!hasSourceAttribute() && !m_element->firstChild())
@@ -171,8 +179,10 @@
if (!isScriptTypeSupported(supportLegacyTypes))
return false;
- if (wasParserInserted)
+ if (wasParserInserted) {
m_parserInserted = true;
+ m_forceAsync = false;
+ }
m_alreadyStarted = true;
@@ -207,6 +217,10 @@
else if (!hasSourceAttribute() && m_parserInserted && !m_element->document()->haveStylesheetsLoaded()) {
m_willBeParserExecuted = true;
m_readyToBeParserExecuted = true;
+ } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) {
+ m_willExecuteInOrder = true;
+ m_element->document()->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION);
+ m_cachedScript->addClient(this);
} else if (hasSourceAttribute())
m_cachedScript->addClient(this);
else
@@ -286,7 +300,10 @@
{
ASSERT(!m_willBeParserExecuted);
ASSERT_UNUSED(o, o == m_cachedScript);
- m_element->document()->asyncScriptRunner()->executeScriptSoon(this, m_cachedScript);
+ if (m_willExecuteInOrder)
+ m_element->document()->scriptRunner()->notifyInOrderScriptReady();
+ else
+ m_element->document()->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION);
m_cachedScript = 0;
}