Skip to content
Permalink
Browse files
2010-09-09 Tony Gentilcore <tonyg@chromium.org>
        Reviewed by Adam Barth.

        Support <script async> as specified by HTML5
        https://bugs.webkit.org/show_bug.cgi?id=45310

        * fast/dom/Document/readystate.html: Dynamically inserted scripts now block the load event like in FF4. So move the finishJSTest call to load.
        * fast/dom/Document/readystate-expected.txt: Dynamically inserted script now runs before load during "interactive" phase.
        * fast/dom/HTMLScriptElement/async-inline-script-expected.txt: Added.
        * fast/dom/HTMLScriptElement/async-inline-script.html: Added. The async attribute doesn't apply to inline scripts, so check that they execute in order.
        * fast/dom/HTMLScriptElement/async-onbeforeload-expected.txt: Added.
        * fast/dom/HTMLScriptElement/async-onbeforeload.html: Added. Check that onbeforeload events fire synchronously and that they may be cancelled.
        * fast/dom/HTMLScriptElement/async-write-expected.txt: Added.
        * fast/dom/HTMLScriptElement/async-write.html: Added. Check that writes from async scripts are neutralized.
        * fast/dom/HTMLScriptElement/resources/async.js: Added.
        * http/tests/misc/async-and-defer-script-expected.txt: Added.
        * http/tests/misc/async-and-defer-script.html: Added. The async attributes takes precendence over the defer attribute.
        Check that a script which has both async and defer acts as async by ensuring it loads after DOMContentLoaded.
        A deferred scripts would block DCL.
        * http/tests/misc/resources/async-script.js: Added.
        * http/tests/misc/resources/slow-async-script.cgi: Added.
        * http/tests/misc/script-async-expected.txt: Added.
        * http/tests/misc/script-async.html: Added. Test general execution order of deferred scripts.
        The test checks for multiple valid orders since it is indeterminate.
2010-09-09  Tony Gentilcore  <tonyg@chromium.org>

        Reviewed by Adam Barth.

        Support <script async> as specified by HTML5
        https://bugs.webkit.org/show_bug.cgi?id=45310

        Tests: fast/dom/HTMLScriptElement/async-inline-script.html
               fast/dom/HTMLScriptElement/async-onbeforeload.html
               fast/dom/HTMLScriptElement/async-write.html
               http/tests/misc/async-and-defer-script.html
               http/tests/misc/script-async.html

        * dom/AsyncScriptRunner.cpp:
        (WebCore::AsyncScriptRunner::AsyncScriptRunner):
        (WebCore::AsyncScriptRunner::~AsyncScriptRunner):
        (WebCore::AsyncScriptRunner::executeScriptSoon): Increment the delay count when a task to execute scripts is queued up.
        (WebCore::AsyncScriptRunner::timerFired): decrementLoadEventDelayCount handles calling checkCompleted().
        * dom/AsyncScriptRunner.h:
        (WebCore::AsyncScriptRunner::create):
        * dom/Document.cpp:
        (WebCore::Document::Document):
        * dom/ScriptElement.cpp:
        (WebCore::ScriptElement::insertedIntoDocument): Treats async scripts just like a dynamically inserted script element rather than a parser inserted one.
        * html/parser/HTMLScriptRunner.cpp:
        (WebCore::HTMLScriptRunner::runScript):

Canonical link: https://commits.webkit.org/57899@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@67163 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
tonygentilcore committed Sep 10, 2010
1 parent 2e1da42 commit 4829c1348c4d71d394978c50d399894bd9edc9dc
@@ -1,3 +1,29 @@
2010-09-09 Tony Gentilcore <tonyg@chromium.org>

Reviewed by Adam Barth.

Support <script async> as specified by HTML5
https://bugs.webkit.org/show_bug.cgi?id=45310

* fast/dom/Document/readystate.html: Dynamically inserted scripts now block the load event like in FF4. So move the finishJSTest call to load.
* fast/dom/Document/readystate-expected.txt: Dynamically inserted script now runs before load during "interactive" phase.
* fast/dom/HTMLScriptElement/async-inline-script-expected.txt: Added.
* fast/dom/HTMLScriptElement/async-inline-script.html: Added. The async attribute doesn't apply to inline scripts, so check that they execute in order.
* fast/dom/HTMLScriptElement/async-onbeforeload-expected.txt: Added.
* fast/dom/HTMLScriptElement/async-onbeforeload.html: Added. Check that onbeforeload events fire synchronously and that they may be cancelled.
* fast/dom/HTMLScriptElement/async-write-expected.txt: Added.
* fast/dom/HTMLScriptElement/async-write.html: Added. Check that writes from async scripts are neutralized.
* fast/dom/HTMLScriptElement/resources/async.js: Added.
* http/tests/misc/async-and-defer-script-expected.txt: Added.
* http/tests/misc/async-and-defer-script.html: Added. The async attributes takes precendence over the defer attribute.
Check that a script which has both async and defer acts as async by ensuring it loads after DOMContentLoaded.
A deferred scripts would block DCL.
* http/tests/misc/resources/async-script.js: Added.
* http/tests/misc/resources/slow-async-script.cgi: Added.
* http/tests/misc/script-async-expected.txt: Added.
* http/tests/misc/script-async.html: Added. Test general execution order of deferred scripts.
The test checks for multiple valid orders since it is indeterminate.

2010-09-09 Dirk Pranke <dpranke@chromium.org>

Unreviewed, expectations update.
@@ -3,7 +3,7 @@ PASS document.readyState is "loading"
PASS document.readyState is "loading"
PASS document.readyState is "interactive"
PASS document.readyState is "interactive"
PASS document.readyState is "complete"
PASS document.readyState is "interactive"
PASS document.readyState is "complete"
PASS successfullyParsed is true

@@ -4,7 +4,7 @@
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
</head>
<body onload="shouldBeEqualToString('document.readyState', 'complete');">
<body onload="shouldBeEqualToString('document.readyState', 'complete');finishJSTest();">
Tests that the document's readyState is set properly at various phases during load.
<div id="console"></div>
<script defer src="data:text/javascript,shouldBeEqualToString('document.readyState', 'interactive');"></script>
@@ -18,8 +18,7 @@
shouldBeEqualToString("document.readyState", "interactive");

var el = document.createElement('script');
el.src = "data:text/javascript,shouldBeEqualToString('document.readyState', 'complete');";
el.onload = function() { finishJSTest(); }
el.src = "data:text/javascript,shouldBeEqualToString('document.readyState', 'interactive');";
document.getElementsByTagName('head')[0].appendChild(el);
}, false);

@@ -0,0 +1,4 @@
Checks that inline scripts are not async.
1
2

@@ -0,0 +1,17 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
</head>
<body>
Checks that inline scripts are not async.
<div id="console"></div>
<script async>
debug(1);
</script>
<script>
debug(2);
</script>
</body>
</html>
@@ -0,0 +1,10 @@
Checks that async scripts fire onbeforeload immediately and that it is cancellable.
cancelled onbeforeload async
onbeforeload async
onbeforeload external
async
load
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,17 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../../js/resources/js-test-style.css">
<script src="../../js/resources/js-test-pre.js"></script>
</head>
<body onload="debug('load');finishJSTest();">
Checks that async scripts fire onbeforeload immediately and that it is cancellable.
<div id="console"></div>
<script>var jsTestIsAsync = true;</script>
<script src="resources/shouldnotexecute.js" onbeforeload="debug('cancelled onbeforeload async'); return false;" async></script>
<script src="resources/async.js" onbeforeload="debug('onbeforeload async'); return true;" async></script>
<script src="data:text/javascript," onbeforeload="debug('onbeforeload external'); return true;"></script>
<script>var successfullyParsed = true;</script>
<script src="../../js/resources/js-test-post.js"></script>
</body>
</html>
@@ -0,0 +1 @@
PASS
@@ -0,0 +1,6 @@
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();
</script>
PASS
<script async="ASYNC" src="data:text/javascript,document.write('FAIL');"></script>
@@ -0,0 +1 @@
debug("async");
@@ -0,0 +1,8 @@
Checks that the async attribute takes precendence over defer.
DOMContentLoaded
slowAsync
load
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../../js-tests-resources/js-test-style.css">
<script src="../../js-test-resources/js-test-pre.js"></script>
</head>
<body onload="debug('load');finishJSTest();">
Checks that the async attribute takes precendence over defer.
<div id="console"></div>
<script>
var jsTestIsAsync = true;
document.addEventListener("DOMContentLoaded", function() {
debug("DOMContentLoaded");
}, false);
var successfullyParsed = true;
</script>
<script defer async src="http://127.0.0.1:8000/misc/resources/slow-async-script.cgi"></script>
<script src="../../js-test-resources/js-test-post.js"></script>
</body>
</html>
@@ -0,0 +1 @@
debug("async");
@@ -0,0 +1,6 @@
#!/usr/bin/perl -w

print "Content-type: text/javascript\n\n";
sleep(1.0);
print "debug('slowAsync');\n";

@@ -0,0 +1,2 @@
This tests for proper execution order of scripts with the async attribute https://bugs.webkit.org/show_bug.cgi?id=20710.
PASS
@@ -0,0 +1,50 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../js-test-resources/js-test-style.css">
<script src="../../js-test-resources/js-test-pre.js"></script>
</head>
<body onload="test()">
This tests for proper execution order of scripts with the async attribute <a href="https://bugs.webkit.org/show_bug.cgi?id=20710">https://bugs.webkit.org/show_bug.cgi?id=20710</a>.<hr>
<div id="console"></div>
<script type="text/javascript">
var jsTestIsAsync = true;

function debug(msg)
{
if (!window.status_)
window.status_ = '';
window.status_ += ' ' + msg + ' ';
}

document.addEventListener("DOMContentLoaded", function() {
debug('DOMContentLoaded');
}, false);

function test()
{
var expectedA = " async external inline DOMContentLoaded slowAsync ";
var expectedB = " external async inline DOMContentLoaded slowAsync ";
var expectedC = " external inline async DOMContentLoaded slowAsync ";
var expectedD = " external inline DOMContentLoaded async slowAsync ";
var results = "PASS";
if (window.status_ != expectedA && window.status_ != expectedB && window.status_ != expectedC && window.status_ != expectedD)
results = "FAIL: Expected one of '" + expectedA + "' || '" + expectedB + "' || '" + expectedC + "' || '" + expectedD + "', Actual='" + window.status_ + "'";
document.getElementById("console").innerHTML = results;
finishJSTest();
}

var successfullyParsed = true;
</script>
<script src="http://127.0.0.1:8000/misc/resources/slow-async-script.cgi" async="ASYNC"></script>
<script src="http://127.0.0.1:8000/misc/resources/async-script.js" async="ASYNC"></script>
<script src="http://127.0.0.1:8000/misc/resources/external-script.js"></script>
<script>
debug("inline");
</script>
<script src="../../js-test-resources/js-test-post.js"></script>
</body>
</html>


@@ -1,3 +1,30 @@
2010-09-09 Tony Gentilcore <tonyg@chromium.org>

Reviewed by Adam Barth.

Support <script async> as specified by HTML5
https://bugs.webkit.org/show_bug.cgi?id=45310

Tests: fast/dom/HTMLScriptElement/async-inline-script.html
fast/dom/HTMLScriptElement/async-onbeforeload.html
fast/dom/HTMLScriptElement/async-write.html
http/tests/misc/async-and-defer-script.html
http/tests/misc/script-async.html

* dom/AsyncScriptRunner.cpp:
(WebCore::AsyncScriptRunner::AsyncScriptRunner):
(WebCore::AsyncScriptRunner::~AsyncScriptRunner):
(WebCore::AsyncScriptRunner::executeScriptSoon): Increment the delay count when a task to execute scripts is queued up.
(WebCore::AsyncScriptRunner::timerFired): decrementLoadEventDelayCount handles calling checkCompleted().
* dom/AsyncScriptRunner.h:
(WebCore::AsyncScriptRunner::create):
* dom/Document.cpp:
(WebCore::Document::Document):
* dom/ScriptElement.cpp:
(WebCore::ScriptElement::insertedIntoDocument): Treats async scripts just like a dynamically inserted script element rather than a parser inserted one.
* html/parser/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::runScript):

2010-09-09 Alexey Marinichev <amarinichev@chromium.org>

Reviewed by James Robinson.
@@ -27,20 +27,25 @@
#include "AsyncScriptRunner.h"

#include "CachedScript.h"
#include "Document.h"
#include "Element.h"
#include "ScriptElement.h"

namespace WebCore {

AsyncScriptRunner::AsyncScriptRunner()
: m_timer(this, &AsyncScriptRunner::timerFired)
AsyncScriptRunner::AsyncScriptRunner(Document* document)
: m_document(document)
, m_timer(this, &AsyncScriptRunner::timerFired)
{
ASSERT(document);
}

AsyncScriptRunner::~AsyncScriptRunner()
{
for (size_t i = 0; i < m_scriptsToExecuteSoon.size(); ++i)
m_scriptsToExecuteSoon[i].first->element()->deref(); // Balances ref() in executeScriptSoon().
for (size_t i = 0; i < m_scriptsToExecuteSoon.size(); ++i) {
m_scriptsToExecuteSoon[i].first->element()->deref(); // Balances ref() in executeScriptSoon().
m_document->decrementLoadEventDelayCount();
}
}

void AsyncScriptRunner::executeScriptSoon(ScriptElementData* data, CachedResourceHandle<CachedScript> cachedScript)
@@ -51,6 +56,7 @@ void AsyncScriptRunner::executeScriptSoon(ScriptElementData* data, CachedResourc
ASSERT(element);
ASSERT(element->inDocument());

m_document->incrementLoadEventDelayCount();
m_scriptsToExecuteSoon.append(make_pair(data, cachedScript));
element->ref(); // Balanced by deref()s in timerFired() and dtor.
if (!m_timer.isActive())
@@ -78,6 +84,7 @@ void AsyncScriptRunner::timerFired(Timer<AsyncScriptRunner>* timer)
for (size_t i = 0; i < size; ++i) {
scripts[i].first->execute(scripts[i].second.get());
scripts[i].first->element()->deref(); // Balances ref() in executeScriptSoon().
m_document->decrementLoadEventDelayCount();
}
}

@@ -35,11 +35,12 @@
namespace WebCore {

class CachedScript;
class Document;
class ScriptElementData;

class AsyncScriptRunner : public Noncopyable {
public:
static PassOwnPtr<AsyncScriptRunner> create() { return new AsyncScriptRunner(); }
static PassOwnPtr<AsyncScriptRunner> create(Document* document) { return new AsyncScriptRunner(document); }
~AsyncScriptRunner();

void executeScriptSoon(ScriptElementData*, CachedResourceHandle<CachedScript>);
@@ -48,10 +49,11 @@ class AsyncScriptRunner : public Noncopyable {
void resume();

private:
AsyncScriptRunner();
AsyncScriptRunner(Document*);

void timerFired(Timer<AsyncScriptRunner>*);

Document* m_document;
Vector<std::pair<ScriptElementData*, CachedResourceHandle<CachedScript> > > m_scriptsToExecuteSoon;
Timer<AsyncScriptRunner> m_timer;
};
@@ -371,7 +371,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
, m_startTime(currentTime())
, m_overMinimumLayoutThreshold(false)
, m_extraLayoutDelay(0)
, m_asyncScriptRunner(AsyncScriptRunner::create())
, m_asyncScriptRunner(AsyncScriptRunner::create(this))
, m_xmlVersion("1.0")
, m_xmlStandalone(false)
, m_savedRenderer(0)
@@ -52,7 +52,7 @@ namespace WebCore {

void ScriptElement::insertedIntoDocument(ScriptElementData& data, const String& sourceUrl)
{
if (data.createdByParser())
if (data.createdByParser() && !data.isAsynchronous())
return;

// http://www.whatwg.org/specs/web-apps/current-work/#script
@@ -321,7 +321,9 @@ void HTMLScriptRunner::runScript(Element* script, int startingLineNumber)
notImplemented(); // event for support

if (script->hasAttribute(srcAttr)) {
// FIXME: Handle async.
if (script->hasAttribute(asyncAttr)) // Async takes precendence over defer.
return; // Asynchronous scripts handle themselves.

if (script->hasAttribute(deferAttr))
requestDeferredScript(script);
else

0 comments on commit 4829c13

Please sign in to comment.