[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

tonyg at chromium.org tonyg at chromium.org
Wed Dec 22 12:56:03 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 65960d10012f97bd76a51e77724ef94a4864585c
Author: tonyg at chromium.org <tonyg at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Sep 2 09:05:59 2010 +0000

    2010-09-02  Tony Gentilcore  <tonyg at chromium.org>
    
            Reviewed by Adam Barth.
    
            Support <script defer> as specified by HTML5
            https://bugs.webkit.org/show_bug.cgi?id=40934
    
            * fast/dom/HTMLScriptElement/defer-double-defer-write-expected.txt: Added.
            * fast/dom/HTMLScriptElement/defer-double-defer-write.html: Added. Tests that a write of a deferred script from a deferred script will execute when the document is closed. The explicit close is necessary because this is a script created parser.
            * fast/dom/HTMLScriptElement/defer-double-write-expected.txt: Added.
            * fast/dom/HTMLScriptElement/defer-double-write.html: Added. Tests that a script block written from a deferred script will write into the new document.
            * fast/dom/HTMLScriptElement/defer-inline-script-expected.txt: Added.
            * fast/dom/HTMLScriptElement/defer-inline-script.html: Added. Tests that inline scripts are not deferred. This is consistent with HTML5 and inconsistent with IE.
            * fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt: Added.
            * fast/dom/HTMLScriptElement/defer-onbeforeload.html: Added. Tests that the beforeload event is fired immediately and is cancellable.
            * fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt: Added.
            * fast/dom/HTMLScriptElement/defer-script-invalid-url.html: Added. Tests that deferred scripts with invalid URLs are ignored and that subsequent deferred scripts will be run.
            * fast/dom/HTMLScriptElement/defer-write-expected.txt: Added.
            * fast/dom/HTMLScriptElement/defer-write.html: Added. Tests that a basic write from a deferred script blows away the document.
            * fast/dom/HTMLScriptElement/resources/defer.js: Added.
            * fast/dom/HTMLScriptElement/resources/external.js: Added.
            * fast/dom/HTMLScriptElement/resources/shouldnotexecute.js: Added.
            * fast/dom/HTMLScriptElement/shouldnotexecute.js: Added.
            * fast/dom/HTMLScriptElement/two-defer-writes-expected.txt: Added.
            * fast/dom/HTMLScriptElement/two-defer-writes.html: Added. Tests that when a document.write from the first deferred script blows away the document, subsequent deferred scripts are not executed.
            * http/tests/misc/resources/defer-script.js: Added.
            * http/tests/misc/resources/external-script.js: Added.
            * http/tests/misc/resources/script-debug-body-background.js: Added.
            * http/tests/misc/resources/script-write-slow-stylesheet.js: Added.
            * http/tests/misc/resources/slow-defer-script.cgi: Added.
            * http/tests/misc/resources/slow-stylesheet.cgi: Added.
            * http/tests/misc/script-defer-after-slow-stylesheet-expected.txt: Added.
            * http/tests/misc/script-defer-after-slow-stylesheet.html: Added. Tests that deferred scripts respect blocking stylesheets.
            * http/tests/misc/script-defer-expected.txt: Added.
            * http/tests/misc/script-defer.html: Added. Tests basic ordering of deferred scripts.
    2010-09-02  Tony Gentilcore  <tonyg at chromium.org>
    
            Reviewed by Adam Barth.
    
            Support <script defer> as specified by HTML5
            https://bugs.webkit.org/show_bug.cgi?id=40934
    
            Tests: fast/dom/HTMLScriptElement/defer-double-defer-write.html
                   fast/dom/HTMLScriptElement/defer-double-write.html
                   fast/dom/HTMLScriptElement/defer-inline-script.html
                   fast/dom/HTMLScriptElement/defer-onbeforeload.html
                   fast/dom/HTMLScriptElement/defer-script-invalid-url.html
                   fast/dom/HTMLScriptElement/defer-write.html
                   fast/dom/HTMLScriptElement/two-defer-writes.html
                   http/tests/misc/script-defer-after-slow-stylesheet.html
                   http/tests/misc/script-defer.html
    
            * dom/Document.cpp:
            (WebCore::Document::open): Allow implicit open for writes() while executing deferred scripts.
            * dom/DocumentParser.cpp:
            (WebCore::DocumentParser::DocumentParser):
            (WebCore::DocumentParser::startParsing):
            (WebCore::DocumentParser::prepareToStopParsing): If called when stopped or detached, it shouldn't reset to stopping.
            (WebCore::DocumentParser::stopParsing):
            (WebCore::DocumentParser::detach):
            * dom/DocumentParser.h:
            (WebCore::DocumentParser::isParsing):
            (WebCore::DocumentParser::isActive):
            (WebCore::DocumentParser::isStopping):
            (WebCore::DocumentParser::isDetached):
            * dom/RawDataDocumentParser.h:
            (WebCore::RawDataDocumentParser::finish):
            * dom/XMLDocumentParser.cpp:
            (WebCore::XMLDocumentParser::append):
            (WebCore::XMLDocumentParser::exitText):
            * dom/XMLDocumentParserLibxml2.cpp:
            (WebCore::XMLDocumentParser::doWrite):
            (WebCore::XMLDocumentParser::startElementNs):
            (WebCore::XMLDocumentParser::endElementNs):
            (WebCore::XMLDocumentParser::characters):
            (WebCore::XMLDocumentParser::error):
            (WebCore::XMLDocumentParser::processingInstruction):
            (WebCore::XMLDocumentParser::cdataBlock):
            (WebCore::XMLDocumentParser::comment):
            (WebCore::XMLDocumentParser::internalSubset):
            (WebCore::XMLDocumentParser::initializeParserContext):
            (WebCore::XMLDocumentParser::doEnd):
            * html/parser/HTMLDocumentParser.cpp:
            (WebCore::HTMLDocumentParser::prepareToStopParsing):
            (WebCore::HTMLDocumentParser::pumpTokenizerIfPossible):
            (WebCore::HTMLDocumentParser::pumpTokenizer):
            (WebCore::HTMLDocumentParser::insert):
            (WebCore::HTMLDocumentParser::append):
            (WebCore::HTMLDocumentParser::end):
            (WebCore::HTMLDocumentParser::attemptToEnd):
            (WebCore::HTMLDocumentParser::endIfDelayed):
            (WebCore::HTMLDocumentParser::notifyFinished):
            * html/parser/HTMLDocumentParser.h:
            * html/parser/HTMLScriptRunner.cpp:
            (WebCore::HTMLScriptRunner::~HTMLScriptRunner):
            (WebCore::HTMLScriptRunner::executeParsingBlockingScript):
            (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
            (WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing):
            (WebCore::HTMLScriptRunner::requestDeferredScript):
            (WebCore::HTMLScriptRunner::runScript):
            * html/parser/HTMLScriptRunner.h:
            * loader/ImageDocument.cpp:
            (WebCore::ImageDocumentParser::finish):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66649 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 292d0b9..dfe4fb0 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,39 @@
+2010-09-02  Tony Gentilcore  <tonyg at chromium.org>
+
+        Reviewed by Adam Barth.
+
+        Support <script defer> as specified by HTML5
+        https://bugs.webkit.org/show_bug.cgi?id=40934
+
+        * fast/dom/HTMLScriptElement/defer-double-defer-write-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/defer-double-defer-write.html: Added. Tests that a write of a deferred script from a deferred script will execute when the document is closed. The explicit close is necessary because this is a script created parser.
+        * fast/dom/HTMLScriptElement/defer-double-write-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/defer-double-write.html: Added. Tests that a script block written from a deferred script will write into the new document.
+        * fast/dom/HTMLScriptElement/defer-inline-script-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/defer-inline-script.html: Added. Tests that inline scripts are not deferred. This is consistent with HTML5 and inconsistent with IE.
+        * fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/defer-onbeforeload.html: Added. Tests that the beforeload event is fired immediately and is cancellable.
+        * fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/defer-script-invalid-url.html: Added. Tests that deferred scripts with invalid URLs are ignored and that subsequent deferred scripts will be run.
+        * fast/dom/HTMLScriptElement/defer-write-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/defer-write.html: Added. Tests that a basic write from a deferred script blows away the document.
+        * fast/dom/HTMLScriptElement/resources/defer.js: Added.
+        * fast/dom/HTMLScriptElement/resources/external.js: Added.
+        * fast/dom/HTMLScriptElement/resources/shouldnotexecute.js: Added.
+        * fast/dom/HTMLScriptElement/shouldnotexecute.js: Added.
+        * fast/dom/HTMLScriptElement/two-defer-writes-expected.txt: Added.
+        * fast/dom/HTMLScriptElement/two-defer-writes.html: Added. Tests that when a document.write from the first deferred script blows away the document, subsequent deferred scripts are not executed.
+        * http/tests/misc/resources/defer-script.js: Added.
+        * http/tests/misc/resources/external-script.js: Added.
+        * http/tests/misc/resources/script-debug-body-background.js: Added.
+        * http/tests/misc/resources/script-write-slow-stylesheet.js: Added.
+        * http/tests/misc/resources/slow-defer-script.cgi: Added.
+        * http/tests/misc/resources/slow-stylesheet.cgi: Added.
+        * http/tests/misc/script-defer-after-slow-stylesheet-expected.txt: Added.
+        * http/tests/misc/script-defer-after-slow-stylesheet.html: Added. Tests that deferred scripts respect blocking stylesheets.
+        * http/tests/misc/script-defer-expected.txt: Added.
+        * http/tests/misc/script-defer.html: Added. Tests basic ordering of deferred scripts.
+
 2010-09-02  Philippe Normand  <pnormand at igalia.com>
 
         Unreviewed, skipping new failing media test.
diff --git a/LayoutTests/editing/selection/5136696-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-defer-write-expected.txt
old mode 100644
new mode 100755
similarity index 100%
copy from LayoutTests/editing/selection/5136696-expected.txt
copy to LayoutTests/fast/dom/HTMLScriptElement/defer-double-defer-write-expected.txt
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-double-defer-write.html b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-defer-write.html
new file mode 100644
index 0000000..0412050
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-defer-write.html
@@ -0,0 +1,6 @@
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+FAIL
+<script defer src="data:text/javascript,document.write('FAIL'); document.write('<script defer src=\'data:text/javascript,document.write(&quot;PASS&quot;);\'></script>'); document.close();"></script>
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-double-write-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-write-expected.txt
new file mode 100755
index 0000000..8d04f96
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-write-expected.txt
@@ -0,0 +1 @@
+1 2
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-double-write.html b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-write.html
new file mode 100644
index 0000000..e55e1d3
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-double-write.html
@@ -0,0 +1,6 @@
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+FAIL
+<script defer src="data:text/javascript,document.writeln(1); document.write('<script src=\'data:text/javascript,document.writeln(2)\'></script>');"></script>
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script-expected.txt
new file mode 100755
index 0000000..beaaad8
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script-expected.txt
@@ -0,0 +1,4 @@
+Checks that inline scripts are not deferred.
+1
+2
+
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script.html b/LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script.html
new file mode 100644
index 0000000..a15c201
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-inline-script.html
@@ -0,0 +1,15 @@
+<!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 deferred.
+<div id="console"></div>
+<script src="data:text/javascript,debug(2);" defer></script>
+<script defer>
+  debug(1);
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt
new file mode 100644
index 0000000..2eb56c9
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt
@@ -0,0 +1,7 @@
+Checks that deferred scripts fire onbeforeload immediately and that it is cancellable.
+cancelled onbeforeload defer
+onbeforeload defer
+onbeforeload external
+external
+defer
+
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload.html b/LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload.html
new file mode 100644
index 0000000..a22b184
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload.html
@@ -0,0 +1,14 @@
+<!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 deferred scripts fire onbeforeload immediately and that it is cancellable.
+<div id="console"></div>
+<script src="resources/shouldnotexecute.js" onbeforeload="debug('cancelled onbeforeload defer'); return false;" defer></script>
+<script src="resources/defer.js" onbeforeload="debug('onbeforeload defer'); return true;" defer></script>
+<script src="resources/external.js" onbeforeload="debug('onbeforeload external'); return true;"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt
new file mode 100644
index 0000000..045af1d
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt
@@ -0,0 +1,3 @@
+Checks that deferred scripts with invalid URLs are ignored and subsequent deferred scripts executed.
+defer
+
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url.html b/LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url.html
new file mode 100644
index 0000000..bf6cee4
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url.html
@@ -0,0 +1,13 @@
+<!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 deferred scripts with invalid URLs are ignored and subsequent deferred scripts executed.
+<div id="console"></div>
+<script src="http://localhost:999999/" defer></script>
+<script src="resources/defer.js" defer></script>
+</body>
+</html>
diff --git a/LayoutTests/editing/selection/5136696-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/defer-write-expected.txt
similarity index 100%
copy from LayoutTests/editing/selection/5136696-expected.txt
copy to LayoutTests/fast/dom/HTMLScriptElement/defer-write-expected.txt
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/defer-write.html b/LayoutTests/fast/dom/HTMLScriptElement/defer-write.html
new file mode 100644
index 0000000..0c0bbff
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/defer-write.html
@@ -0,0 +1,6 @@
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+FAIL
+<script defer src="data:text/javascript,document.write('PASS');"></script>
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/resources/defer.js b/LayoutTests/fast/dom/HTMLScriptElement/resources/defer.js
new file mode 100644
index 0000000..fc67db4
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/resources/defer.js
@@ -0,0 +1 @@
+debug("defer");
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/resources/external.js b/LayoutTests/fast/dom/HTMLScriptElement/resources/external.js
new file mode 100644
index 0000000..fbad465
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/resources/external.js
@@ -0,0 +1 @@
+debug("external");
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/resources/shouldnotexecute.js b/LayoutTests/fast/dom/HTMLScriptElement/resources/shouldnotexecute.js
new file mode 100644
index 0000000..c0d6954
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/resources/shouldnotexecute.js
@@ -0,0 +1 @@
+debug("FAIL");
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/shouldnotexecute.js b/LayoutTests/fast/dom/HTMLScriptElement/shouldnotexecute.js
new file mode 100644
index 0000000..fc67db4
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/shouldnotexecute.js
@@ -0,0 +1 @@
+debug("defer");
diff --git a/LayoutTests/editing/selection/5136696-expected.txt b/LayoutTests/fast/dom/HTMLScriptElement/two-defer-writes-expected.txt
similarity index 100%
copy from LayoutTests/editing/selection/5136696-expected.txt
copy to LayoutTests/fast/dom/HTMLScriptElement/two-defer-writes-expected.txt
diff --git a/LayoutTests/fast/dom/HTMLScriptElement/two-defer-writes.html b/LayoutTests/fast/dom/HTMLScriptElement/two-defer-writes.html
new file mode 100644
index 0000000..4b0d378
--- /dev/null
+++ b/LayoutTests/fast/dom/HTMLScriptElement/two-defer-writes.html
@@ -0,0 +1,7 @@
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+FAIL
+<script defer src="data:text/javascript,document.write('PASS');"></script>
+<script defer src="data:text/javascript,document.write('FAIL');"></script>
diff --git a/LayoutTests/http/tests/misc/resources/defer-script.js b/LayoutTests/http/tests/misc/resources/defer-script.js
new file mode 100644
index 0000000..fc67db4
--- /dev/null
+++ b/LayoutTests/http/tests/misc/resources/defer-script.js
@@ -0,0 +1 @@
+debug("defer");
diff --git a/LayoutTests/http/tests/misc/resources/external-script.js b/LayoutTests/http/tests/misc/resources/external-script.js
new file mode 100644
index 0000000..fbad465
--- /dev/null
+++ b/LayoutTests/http/tests/misc/resources/external-script.js
@@ -0,0 +1 @@
+debug("external");
diff --git a/LayoutTests/http/tests/misc/resources/script-debug-body-background.js b/LayoutTests/http/tests/misc/resources/script-debug-body-background.js
new file mode 100644
index 0000000..6fbe7a1
--- /dev/null
+++ b/LayoutTests/http/tests/misc/resources/script-debug-body-background.js
@@ -0,0 +1 @@
+shouldBeEqualToString("getComputedStyle(document.body)['background-color']", "rgb(255, 0, 0)");
diff --git a/LayoutTests/http/tests/misc/resources/script-write-slow-stylesheet.js b/LayoutTests/http/tests/misc/resources/script-write-slow-stylesheet.js
new file mode 100644
index 0000000..ed11eb5
--- /dev/null
+++ b/LayoutTests/http/tests/misc/resources/script-write-slow-stylesheet.js
@@ -0,0 +1 @@
+document.write('<link rel="stylesheet" href="http://127.0.0.1:8000/misc/resources/slow-stylesheet.cgi">');
diff --git a/LayoutTests/http/tests/misc/resources/slow-defer-script.cgi b/LayoutTests/http/tests/misc/resources/slow-defer-script.cgi
new file mode 100755
index 0000000..a98d3d5
--- /dev/null
+++ b/LayoutTests/http/tests/misc/resources/slow-defer-script.cgi
@@ -0,0 +1,5 @@
+#!/usr/bin/perl -w
+
+print "Content-type: text/javascript\n\n";
+sleep(0.5);
+print "debug('slowDefer');\n";
diff --git a/LayoutTests/http/tests/misc/resources/slow-stylesheet.cgi b/LayoutTests/http/tests/misc/resources/slow-stylesheet.cgi
new file mode 100755
index 0000000..fcddca4
--- /dev/null
+++ b/LayoutTests/http/tests/misc/resources/slow-stylesheet.cgi
@@ -0,0 +1,5 @@
+#!/usr/bin/perl -w
+
+print "Content-type: text/css\n\n";
+sleep(0.5);
+print "body { background-color: #FF0000 }\n";
diff --git a/LayoutTests/http/tests/misc/script-defer-after-slow-stylesheet-expected.txt b/LayoutTests/http/tests/misc/script-defer-after-slow-stylesheet-expected.txt
new file mode 100644
index 0000000..5245763
--- /dev/null
+++ b/LayoutTests/http/tests/misc/script-defer-after-slow-stylesheet-expected.txt
@@ -0,0 +1,10 @@
+This tests that an inline slow stylesheet executes before deferred scripts.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS getComputedStyle(document.body)['background-color'] is "rgb(255, 0, 0)"
+DOMContentLoaded
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/misc/script-defer-after-slow-stylesheet.html b/LayoutTests/http/tests/misc/script-defer-after-slow-stylesheet.html
new file mode 100644
index 0000000..06ec849
--- /dev/null
+++ b/LayoutTests/http/tests/misc/script-defer-after-slow-stylesheet.html
@@ -0,0 +1,32 @@
+<!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>
+<dvi id="description"></div>
+<div id="console"></div>
+<script type="text/javascript">
+description('This tests that an inline slow stylesheet executes before deferred scripts.');
+
+var jsTestIsAsync = true;
+
+document.addEventListener("DOMContentLoaded", function() {
+  debug('DOMContentLoaded');
+
+  finishJSTest();
+}, false);
+</script>
+
+<script src="http://127.0.0.1:8000/misc/resources/script-debug-body-background.
+js" defer="defer"></script>
+<link rel="stylesheet" href="http://127.0.0.1:8000/misc/resources/slow-styleshe
+et.cgi">
+<script>
+var successfullyParsed = true;
+</script>
+<script src="../../js-test-resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/misc/script-defer-expected.txt b/LayoutTests/http/tests/misc/script-defer-expected.txt
new file mode 100644
index 0000000..bfcaa6e
--- /dev/null
+++ b/LayoutTests/http/tests/misc/script-defer-expected.txt
@@ -0,0 +1,8 @@
+This tests for proper execution order of scripts with the defer attribute https://bugs.webkit.org/show_bug.cgi?id=20710.
+external
+inline
+slowDefer
+defer
+DOMContentLoaded
+load
+
diff --git a/LayoutTests/http/tests/misc/script-defer.html b/LayoutTests/http/tests/misc/script-defer.html
new file mode 100644
index 0000000..95cf8b3
--- /dev/null
+++ b/LayoutTests/http/tests/misc/script-defer.html
@@ -0,0 +1,24 @@
+<!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="debug('load')">
+This tests for proper execution order of scripts with the defer attribute <a href="https://bugs.webkit.org/show_bug.cgi?id=20710">https://bugs.webkit.org/show_bug.cgi?id=20710</a>.
+<div id="console"></div>
+
+<script type="text/javascript">
+document.addEventListener("DOMContentLoaded", function() {
+  debug('DOMContentLoaded');
+}, false);
+</script>
+<script src="http://127.0.0.1:8000/misc/resources/slow-defer-script.cgi" defer="DEFER"></script>
+<script src="http://127.0.0.1:8000/misc/resources/defer-script.js" defer="DEFER"></script>
+<script src="http://127.0.0.1:8000/misc/resources/external-script.js"></script>
+<script>
+debug("inline");
+</script>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index a874b0f..ad76835 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,72 @@
+2010-09-02  Tony Gentilcore  <tonyg at chromium.org>
+
+        Reviewed by Adam Barth.
+
+        Support <script defer> as specified by HTML5
+        https://bugs.webkit.org/show_bug.cgi?id=40934
+
+        Tests: fast/dom/HTMLScriptElement/defer-double-defer-write.html
+               fast/dom/HTMLScriptElement/defer-double-write.html
+               fast/dom/HTMLScriptElement/defer-inline-script.html
+               fast/dom/HTMLScriptElement/defer-onbeforeload.html
+               fast/dom/HTMLScriptElement/defer-script-invalid-url.html
+               fast/dom/HTMLScriptElement/defer-write.html
+               fast/dom/HTMLScriptElement/two-defer-writes.html
+               http/tests/misc/script-defer-after-slow-stylesheet.html
+               http/tests/misc/script-defer.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::open): Allow implicit open for writes() while executing deferred scripts.
+        * dom/DocumentParser.cpp:
+        (WebCore::DocumentParser::DocumentParser):
+        (WebCore::DocumentParser::startParsing):
+        (WebCore::DocumentParser::prepareToStopParsing): If called when stopped or detached, it shouldn't reset to stopping.
+        (WebCore::DocumentParser::stopParsing):
+        (WebCore::DocumentParser::detach):
+        * dom/DocumentParser.h:
+        (WebCore::DocumentParser::isParsing):
+        (WebCore::DocumentParser::isActive):
+        (WebCore::DocumentParser::isStopping):
+        (WebCore::DocumentParser::isDetached):
+        * dom/RawDataDocumentParser.h:
+        (WebCore::RawDataDocumentParser::finish):
+        * dom/XMLDocumentParser.cpp:
+        (WebCore::XMLDocumentParser::append):
+        (WebCore::XMLDocumentParser::exitText):
+        * dom/XMLDocumentParserLibxml2.cpp:
+        (WebCore::XMLDocumentParser::doWrite):
+        (WebCore::XMLDocumentParser::startElementNs):
+        (WebCore::XMLDocumentParser::endElementNs):
+        (WebCore::XMLDocumentParser::characters):
+        (WebCore::XMLDocumentParser::error):
+        (WebCore::XMLDocumentParser::processingInstruction):
+        (WebCore::XMLDocumentParser::cdataBlock):
+        (WebCore::XMLDocumentParser::comment):
+        (WebCore::XMLDocumentParser::internalSubset):
+        (WebCore::XMLDocumentParser::initializeParserContext):
+        (WebCore::XMLDocumentParser::doEnd):
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::prepareToStopParsing):
+        (WebCore::HTMLDocumentParser::pumpTokenizerIfPossible):
+        (WebCore::HTMLDocumentParser::pumpTokenizer):
+        (WebCore::HTMLDocumentParser::insert):
+        (WebCore::HTMLDocumentParser::append):
+        (WebCore::HTMLDocumentParser::end):
+        (WebCore::HTMLDocumentParser::attemptToEnd):
+        (WebCore::HTMLDocumentParser::endIfDelayed):
+        (WebCore::HTMLDocumentParser::notifyFinished):
+        * html/parser/HTMLDocumentParser.h:
+        * html/parser/HTMLScriptRunner.cpp:
+        (WebCore::HTMLScriptRunner::~HTMLScriptRunner):
+        (WebCore::HTMLScriptRunner::executeParsingBlockingScript):
+        (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
+        (WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing):
+        (WebCore::HTMLScriptRunner::requestDeferredScript):
+        (WebCore::HTMLScriptRunner::runScript):
+        * html/parser/HTMLScriptRunner.h:
+        * loader/ImageDocument.cpp:
+        (WebCore::ImageDocumentParser::finish):
+
 2010-09-02  Ilya Sherman  <isherman at google.com>
 
         Reviewed by Eric Seidel.
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp
index 741f98a..dbf447d 100644
--- a/WebCore/dom/Document.cpp
+++ b/WebCore/dom/Document.cpp
@@ -1823,7 +1823,7 @@ void Document::open(Document* ownerDocument)
 
     if (m_frame) {
         ScriptableDocumentParser* parser = scriptableDocumentParser();
-        if (m_frame->loader()->isLoadingMainResource() || (parser && parser->isExecutingScript()))
+        if (m_frame->loader()->isLoadingMainResource() || (parser && parser->isParsing() && parser->isExecutingScript()))
             return;
 
         if (m_frame->loader()->state() == FrameStateProvisional)
diff --git a/WebCore/dom/DocumentParser.cpp b/WebCore/dom/DocumentParser.cpp
index cc4c61b..639860a 100644
--- a/WebCore/dom/DocumentParser.cpp
+++ b/WebCore/dom/DocumentParser.cpp
@@ -31,7 +31,7 @@
 namespace WebCore {
 
 DocumentParser::DocumentParser(Document* document)
-    : m_parserStopped(false)
+    : m_state(ParsingState)
     , m_document(document)
 {
     ASSERT(document);
@@ -45,8 +45,25 @@ DocumentParser::~DocumentParser()
     ASSERT(!m_document);
 }
 
+void DocumentParser::startParsing()
+{
+    m_state = ParsingState;
+}
+
+void DocumentParser::prepareToStopParsing()
+{
+    if (m_state == ParsingState)
+        m_state = StoppingState;
+}
+
+void DocumentParser::stopParsing()
+{
+    m_state = StoppedState;
+}
+
 void DocumentParser::detach()
 {
+    m_state = DetachedState;
     m_document = 0;
 }
 
diff --git a/WebCore/dom/DocumentParser.h b/WebCore/dom/DocumentParser.h
index 3c28856..7cc9e7b 100644
--- a/WebCore/dom/DocumentParser.h
+++ b/WebCore/dom/DocumentParser.h
@@ -57,12 +57,29 @@ public:
 
     // FIXME: processingData() is only used by DocumentLoader::isLoadingInAPISense
     // and is very unclear as to what it actually means.  The LegacyHTMLDocumentParser
-    // used to implements it.
+    // used to implement it.
     virtual bool processingData() const { return false; }
 
     // document() will return 0 after detach() is called.
     Document* document() const { ASSERT(m_document); return m_document; }
-    bool isDetached() const { return !m_document; }
+
+    bool isParsing() const { return m_state == ParsingState; }
+    bool isStopping() const { return m_state == StoppingState; }
+    bool isStopped() const { return m_state >= StoppedState; }
+    bool isDetached() const { return m_state == DetachedState; }
+
+    // FIXME: Is this necessary? Does XMLDocumentParserLibxml2 really need to set this?
+    virtual void startParsing();
+
+    // prepareToStop() is used when the EOF token is encountered and parsing is to be
+    // stopped normally.
+    virtual void prepareToStopParsing();
+
+    // stopParsing() is used when a load is canceled/stopped.
+    // stopParsing() is currently different from detach(), but shouldn't be.
+    // It should NOT be ok to call any methods on DocumentParser after either
+    // detach() or stopParsing() but right now only detach() will ASSERT.
+    virtual void stopParsing();
 
     // Document is expected to detach the parser before releasing its ref.
     // After detach, m_document is cleared.  The parser will unwind its
@@ -71,22 +88,18 @@ public:
     // detach is called.
     virtual void detach();
 
-    // stopParsing() is used when a load is canceled/stopped.
-    // stopParsing() is currently different from detach(), but shouldn't be.
-    // It should NOT be ok to call any methods on DocumentParser after either
-    // detach() or stopParsing() but right now only detach() will ASSERT.
-    virtual void stopParsing() { m_parserStopped = true; }
-
 protected:
     DocumentParser(Document*);
 
-    // The parser has buffers, so parsing may continue even after
-    // it stops receiving data. We use m_parserStopped to stop the parser
-    // even when it has buffered data.
-    // FIXME: m_document = 0 could be changed to mean "parser stopped".
-    bool m_parserStopped;
-
 private:
+    enum ParserState {
+        ParsingState,
+        StoppingState,
+        StoppedState,
+        DetachedState
+    };
+    ParserState m_state;
+
     // Every DocumentParser needs a pointer back to the document.
     // m_document will be 0 after the parser is stopped.
     Document* m_document;
diff --git a/WebCore/dom/RawDataDocumentParser.h b/WebCore/dom/RawDataDocumentParser.h
index 093ddaf..9ca36f4 100644
--- a/WebCore/dom/RawDataDocumentParser.h
+++ b/WebCore/dom/RawDataDocumentParser.h
@@ -39,7 +39,7 @@ protected:
 
     virtual void finish()
     {
-        if (!m_parserStopped && !isDetached())
+        if (!isStopped())
             document()->finishedParsing();
     }
 
diff --git a/WebCore/dom/XMLDocumentParser.cpp b/WebCore/dom/XMLDocumentParser.cpp
index 4b76472..5fb8b54 100644
--- a/WebCore/dom/XMLDocumentParser.cpp
+++ b/WebCore/dom/XMLDocumentParser.cpp
@@ -132,7 +132,7 @@ void XMLDocumentParser::append(const SegmentedString& s)
     if (m_sawXSLTransform || !m_sawFirstElement)
         m_originalSourceForTransform += parseString;
 
-    if (isDetached() || m_parserStopped || m_sawXSLTransform)
+    if (isStopped() || m_sawXSLTransform)
         return;
 
     if (m_parserPaused) {
@@ -190,7 +190,7 @@ static inline String toString(const xmlChar* str, unsigned len)
 
 void XMLDocumentParser::exitText()
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (!m_currentNode || !m_currentNode->isTextNode())
diff --git a/WebCore/dom/XMLDocumentParserLibxml2.cpp b/WebCore/dom/XMLDocumentParserLibxml2.cpp
index db94c50..d99ab4b 100644
--- a/WebCore/dom/XMLDocumentParserLibxml2.cpp
+++ b/WebCore/dom/XMLDocumentParserLibxml2.cpp
@@ -660,7 +660,7 @@ void XMLDocumentParser::doWrite(const String& parseString)
 
         // JavaScript (which may be run under the xmlParseChunk callstack) may
         // cause the parser to be stopped or detached.
-        if (isDetached() || m_parserStopped)
+        if (isStopped())
             return;
     }
 
@@ -733,7 +733,7 @@ static inline void handleElementAttributes(Element* newElement, const xmlChar**
 void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
                                   const xmlChar** libxmlNamespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -822,7 +822,7 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha
 
 void XMLDocumentParser::endElementNs()
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -906,7 +906,7 @@ void XMLDocumentParser::endElementNs()
 
 void XMLDocumentParser::characters(const xmlChar* s, int len)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -921,7 +921,7 @@ void XMLDocumentParser::characters(const xmlChar* s, int len)
 
 void XMLDocumentParser::error(ErrorType type, const char* message, va_list args)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
 #if COMPILER(MSVC) || COMPILER(RVCT)
@@ -945,7 +945,7 @@ void XMLDocumentParser::error(ErrorType type, const char* message, va_list args)
 
 void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlChar* data)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -979,7 +979,7 @@ void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlCh
 
 void XMLDocumentParser::cdataBlock(const xmlChar* s, int len)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -997,7 +997,7 @@ void XMLDocumentParser::cdataBlock(const xmlChar* s, int len)
 
 void XMLDocumentParser::comment(const xmlChar* s)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -1034,7 +1034,7 @@ void XMLDocumentParser::endDocument()
 
 void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_parserPaused) {
@@ -1294,7 +1294,7 @@ void XMLDocumentParser::initializeParserContext(const char* chunk)
     sax.ignorableWhitespace = ignorableWhitespaceHandler;
     sax.entityDecl = xmlSAX2EntityDecl;
     sax.initialized = XML_SAX2_MAGIC;
-    m_parserStopped = false;
+    DocumentParser::startParsing();
     m_sawError = false;
     m_sawXSLTransform = false;
     m_sawFirstElement = false;
@@ -1318,11 +1318,11 @@ void XMLDocumentParser::doEnd()
         document()->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets.
         document()->styleSelectorChanged(RecalcStyleImmediately);
         document()->setParsing(true);
-        m_parserStopped = true;
+        DocumentParser::stopParsing();
     }
 #endif
 
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     if (m_context) {
diff --git a/WebCore/dom/XMLDocumentParserQt.cpp b/WebCore/dom/XMLDocumentParserQt.cpp
index dfd6fb1..59bb94c 100644
--- a/WebCore/dom/XMLDocumentParserQt.cpp
+++ b/WebCore/dom/XMLDocumentParserQt.cpp
@@ -199,7 +199,7 @@ void XMLDocumentParser::doWrite(const String& parseString)
 
 void XMLDocumentParser::initializeParserContext(const char*)
 {
-    m_parserStopped = false;
+    DocumentParser::stopParsing();
     m_sawError = false;
     m_sawXSLTransform = false;
     m_sawFirstElement = false;
@@ -213,7 +213,7 @@ void XMLDocumentParser::doEnd()
         document()->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets.
         document()->styleSelectorChanged(RecalcStyleImmediately);
         document()->setParsing(true);
-        m_parserStopped = true;
+        DocumentParser::startParsing();
     }
 #endif
 
@@ -350,7 +350,7 @@ static inline void handleElementAttributes(Element* newElement, const QXmlStream
 
 void XMLDocumentParser::parse()
 {
-    while (!m_parserStopped && !m_parserPaused && !m_stream.atEnd()) {
+    while (!isStopped() && !m_parserPaused && !m_stream.atEnd()) {
         m_stream.readNext();
         switch (m_stream.tokenType()) {
         case QXmlStreamReader::StartDocument: {
diff --git a/WebCore/html/parser/HTMLDocumentParser.cpp b/WebCore/html/parser/HTMLDocumentParser.cpp
index 207bd3e..975fcb8 100644
--- a/WebCore/html/parser/HTMLDocumentParser.cpp
+++ b/WebCore/html/parser/HTMLDocumentParser.cpp
@@ -142,6 +142,28 @@ void HTMLDocumentParser::stopParsing()
     m_parserScheduler.clear(); // Deleting the scheduler will clear any timers.
 }
 
+// This kicks off "Once the user agent stops parsing" as described by:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end
+void HTMLDocumentParser::prepareToStopParsing()
+{
+    ASSERT(!hasInsertionPoint());
+
+    // pumpTokenizer can cause this parser to be detached from the Document,
+    // but we need to ensure it isn't deleted yet.
+    RefPtr<HTMLDocumentParser> protect(this);
+
+    // FIXME: Set the current document readiness to "interactive".
+
+    // NOTE: This pump should only ever emit buffered character tokens,
+    // so ForceSynchronous vs. AllowYield should be meaningless.
+    pumpTokenizerIfPossible(ForceSynchronous);
+
+    DocumentParser::prepareToStopParsing();
+    if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing())
+        return;
+    end();
+}
+
 bool HTMLDocumentParser::processingData() const
 {
     return isScheduledForResume() || inWrite();
@@ -149,7 +171,7 @@ bool HTMLDocumentParser::processingData() const
 
 void HTMLDocumentParser::pumpTokenizerIfPossible(SynchronousMode mode)
 {
-    if (m_parserStopped || m_treeBuilder->isPaused())
+    if (isStopped() || m_treeBuilder->isPaused())
         return;
 
     // Once a resume is scheduled, HTMLParserScheduler controls when we next pump.
@@ -193,8 +215,7 @@ bool HTMLDocumentParser::runScriptsForPausedTreeBuilder()
 
 void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
 {
-    ASSERT(!isDetached());
-    ASSERT(!m_parserStopped);
+    ASSERT(!isStopped());
     ASSERT(!m_treeBuilder->isPaused());
     ASSERT(!isScheduledForResume());
     // ASSERT that this object is both attached to the Document and protected.
@@ -214,7 +235,7 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
         m_token.clear();
 
         // JavaScript may have stopped or detached the parser.
-        if (isDetached() || m_parserStopped)
+        if (isStopped())
             return;
 
         // The parser will pause itself when waiting on a script to load or run.
@@ -226,7 +247,7 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
         m_treeBuilder->setPaused(!shouldContinueParsing);
 
         // JavaScript may have stopped or detached the parser.
-        if (isDetached() || m_parserStopped)
+        if (isStopped())
             return;
 
         if (!shouldContinueParsing)
@@ -275,7 +296,7 @@ bool HTMLDocumentParser::hasInsertionPoint()
 
 void HTMLDocumentParser::insert(const SegmentedString& source)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     // pumpTokenizer can cause this parser to be detached from the Document,
@@ -296,7 +317,7 @@ void HTMLDocumentParser::insert(const SegmentedString& source)
 
 void HTMLDocumentParser::append(const SegmentedString& source)
 {
-    if (m_parserStopped)
+    if (isStopped())
         return;
 
     // pumpTokenizer can cause this parser to be detached from the Document,
@@ -328,14 +349,6 @@ void HTMLDocumentParser::end()
     ASSERT(!isDetached());
     ASSERT(!isScheduledForResume());
 
-    // pumpTokenizer can cause this parser to be detached from the Document,
-    // but we need to ensure it isn't deleted yet.
-    RefPtr<HTMLDocumentParser> protect(this);
-
-    // NOTE: This pump should only ever emit buffered character tokens,
-    // so ForceSynchronous vs. AllowYield should be meaningless.
-    pumpTokenizerIfPossible(ForceSynchronous);
-
     // Informs the the rest of WebCore that parsing is really finished (and deletes this).
     m_treeBuilder->finished();
 }
@@ -349,7 +362,7 @@ void HTMLDocumentParser::attemptToEnd()
         m_endWasDelayed = true;
         return;
     }
-    end();
+    prepareToStopParsing();
 }
 
 void HTMLDocumentParser::endIfDelayed()
@@ -362,7 +375,7 @@ void HTMLDocumentParser::endIfDelayed()
         return;
 
     m_endWasDelayed = false;
-    end();
+    prepareToStopParsing();
 }
 
 void HTMLDocumentParser::finish()
@@ -447,6 +460,11 @@ bool HTMLDocumentParser::shouldLoadExternalScriptFromSrc(const AtomicString& src
 
 void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource)
 {
+    if (isStopping()) {
+        prepareToStopParsing();
+        return;
+    }
+
     // pumpTokenizer can cause this parser to be detached from the Document,
     // but we need to ensure it isn't deleted yet.
     RefPtr<HTMLDocumentParser> protect(this);
diff --git a/WebCore/html/parser/HTMLDocumentParser.h b/WebCore/html/parser/HTMLDocumentParser.h
index da21a2b..a32b439 100644
--- a/WebCore/html/parser/HTMLDocumentParser.h
+++ b/WebCore/html/parser/HTMLDocumentParser.h
@@ -81,6 +81,7 @@ private:
     virtual void append(const SegmentedString&);
     virtual bool finishWasCalled();
     virtual bool processingData() const;
+    virtual void prepareToStopParsing();
     virtual void stopParsing();
     virtual bool isWaitingForScripts() const;
     virtual bool isExecutingScript() const;
diff --git a/WebCore/html/parser/HTMLScriptRunner.cpp b/WebCore/html/parser/HTMLScriptRunner.cpp
index 6d470a0..764bf01 100644
--- a/WebCore/html/parser/HTMLScriptRunner.cpp
+++ b/WebCore/html/parser/HTMLScriptRunner.cpp
@@ -75,6 +75,12 @@ 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()
@@ -129,10 +135,6 @@ void HTMLScriptRunner::executeParsingBlockingScript()
     ASSERT(m_document->haveStylesheetsLoaded());
     ASSERT(isPendingScriptReady(m_parsingBlockingScript));
 
-    // 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);
 }
@@ -142,6 +144,10 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
     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> scriptElement = pendingScript.releaseElementAndClear();
     {
@@ -238,6 +244,24 @@ bool HTMLScriptRunner::executeScriptsWaitingForStylesheets()
     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))
@@ -252,6 +276,16 @@ void HTMLScriptRunner::requestParsingBlockingScript(Element* element)
         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());
@@ -287,8 +321,11 @@ void HTMLScriptRunner::runScript(Element* script, int startingLineNumber)
         notImplemented(); // event for support
 
         if (script->hasAttribute(srcAttr)) {
-            // FIXME: Handle defer and async
-            requestParsingBlockingScript(script);
+            // FIXME: Handle async.
+            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.
diff --git a/WebCore/html/parser/HTMLScriptRunner.h b/WebCore/html/parser/HTMLScriptRunner.h
index ead9289..47c96fd 100644
--- a/WebCore/html/parser/HTMLScriptRunner.h
+++ b/WebCore/html/parser/HTMLScriptRunner.h
@@ -27,6 +27,7 @@
 #define HTMLScriptRunner_h
 
 #include "PendingScript.h"
+#include <wtf/Deque.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/PassRefPtr.h>
 
@@ -56,6 +57,7 @@ public:
     bool executeScriptsWaitingForLoad(CachedResource*);
     bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; }
     bool executeScriptsWaitingForStylesheets();
+    bool executeScriptsWaitingForParsing();
 
     bool isExecutingScript() const { return !!m_scriptNestingLevel; }
 
@@ -71,6 +73,7 @@ private:
     bool executeParsingBlockingScripts();
 
     void requestParsingBlockingScript(Element*);
+    void requestDeferredScript(Element*);
     bool requestPendingScript(PendingScript&, Element*) const;
 
     void runScript(Element*, int startingLineNumber);
@@ -84,6 +87,7 @@ private:
     Document* m_document;
     HTMLScriptRunnerHost* m_host;
     PendingScript m_parsingBlockingScript;
+    Deque<PendingScript> m_scriptsToExecuteAfterParsing; // http://www.whatwg.org/specs/web-apps/current-work/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing
     unsigned m_scriptNestingLevel;
 
     // We only want stylesheet loads to trigger script execution if script
diff --git a/WebCore/loader/ImageDocument.cpp b/WebCore/loader/ImageDocument.cpp
index 702ed9d..cc3c85c 100644
--- a/WebCore/loader/ImageDocument.cpp
+++ b/WebCore/loader/ImageDocument.cpp
@@ -138,7 +138,7 @@ void ImageDocumentParser::appendBytes(DocumentWriter*, const char*, int, bool)
 
 void ImageDocumentParser::finish()
 {
-    if (!m_parserStopped && document()->imageElement()) {
+    if (!isStopped() && document()->imageElement()) {
         CachedImage* cachedImage = document()->cachedImage();
         RefPtr<SharedBuffer> data = document()->frame()->loader()->documentLoader()->mainResourceData();
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list