WebCore: Scripts should not be executed before preceding stylesheets are loaded
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jan 2011 20:46:01 +0000 (20:46 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jan 2011 20:46:01 +0000 (20:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=8852

Reviewed by Dave Hyatt.

Block inline script execution on pending stylesheet loads. This matches
other browsers and HTML5.

Tests: fast/tokenizer/inline-script-stylesheet-write.html
       fast/tokenizer/inline-script-stylesheet.html

* dom/PendingScript.cpp:
(WebCore::PendingScript::releaseElementAndClear):
* dom/PendingScript.h:
(WebCore::PendingScript::PendingScript):
(WebCore::PendingScript::operator=):
(WebCore::PendingScript::startingPosition):
(WebCore::PendingScript::setStartingPosition):
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::process):

This fixes an unrelated bug with beforeload events that was exposed by the other
changes (fast/dom/beforeload/remove-link-in-beforeload-listener.html).

* html/parser/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::sourceFromPendingScript):
(WebCore::HTMLScriptRunner::runScript):

LayoutTests: Scripts should not be executed before preceding stylesheets are loaded
https://bugs.webkit.org/show_bug.cgi?id=8852

Reviewed by Dave Hyatt.

New tests plus a few test with slightly changed output due to different load serialization behavior.

* fast/tokenizer/inline-script-stylesheet-expected.txt: Added.
* fast/tokenizer/inline-script-stylesheet-write-expected.txt: Added.
* fast/tokenizer/inline-script-stylesheet-write.html: Added.
* fast/tokenizer/inline-script-stylesheet.html: Added.
* http/tests/security/mixedContent/insecure-css-in-main-frame-expected.txt:
* platform/mac/fast/repaint/renderer-destruction-by-invalidateSelection-crash-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@74995 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/tokenizer/inline-script-stylesheet-expected.txt [new file with mode: 0644]
LayoutTests/fast/tokenizer/inline-script-stylesheet-write-expected.txt [new file with mode: 0644]
LayoutTests/fast/tokenizer/inline-script-stylesheet-write.html [new file with mode: 0644]
LayoutTests/fast/tokenizer/inline-script-stylesheet.html [new file with mode: 0644]
LayoutTests/http/tests/security/mixedContent/insecure-css-in-main-frame-expected.txt
LayoutTests/platform/mac/fast/repaint/renderer-destruction-by-invalidateSelection-crash-expected.txt
WebCore/ChangeLog
WebCore/dom/PendingScript.cpp
WebCore/dom/PendingScript.h
WebCore/html/HTMLLinkElement.cpp
WebCore/html/parser/HTMLScriptRunner.cpp

index 27243bb..5a356a5 100644 (file)
@@ -1,3 +1,19 @@
+2010-12-31  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        Scripts should not be executed before preceding stylesheets are loaded
+        https://bugs.webkit.org/show_bug.cgi?id=8852
+        
+        New tests plus a few test with slightly changed output due to different load serialization behavior.
+
+        * fast/tokenizer/inline-script-stylesheet-expected.txt: Added.
+        * fast/tokenizer/inline-script-stylesheet-write-expected.txt: Added.
+        * fast/tokenizer/inline-script-stylesheet-write.html: Added.
+        * fast/tokenizer/inline-script-stylesheet.html: Added.
+        * http/tests/security/mixedContent/insecure-css-in-main-frame-expected.txt:
+        * platform/mac/fast/repaint/renderer-destruction-by-invalidateSelection-crash-expected.txt:
+
 2011-01-04  Csaba Osztrogon√°c  <ossy@webkit.org>
 
         Unreviewed trivial fix after r74976.
diff --git a/LayoutTests/fast/tokenizer/inline-script-stylesheet-expected.txt b/LayoutTests/fast/tokenizer/inline-script-stylesheet-expected.txt
new file mode 100644 (file)
index 0000000..185c884
--- /dev/null
@@ -0,0 +1 @@
+Test that inline script blocks on stylesheet load: PASS
diff --git a/LayoutTests/fast/tokenizer/inline-script-stylesheet-write-expected.txt b/LayoutTests/fast/tokenizer/inline-script-stylesheet-write-expected.txt
new file mode 100644 (file)
index 0000000..ade4bb7
--- /dev/null
@@ -0,0 +1 @@
+Test that inline scripts inserted by a script don't block on stylesheet loads: PASS
diff --git a/LayoutTests/fast/tokenizer/inline-script-stylesheet-write.html b/LayoutTests/fast/tokenizer/inline-script-stylesheet-write.html
new file mode 100644 (file)
index 0000000..9b0298e
--- /dev/null
@@ -0,0 +1,11 @@
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+Test that inline scripts inserted by a script don't block on stylesheet loads:
+<script>
+var didRun = false;
+document.write('<link rel=stylesheet href="data:text/css,span{color:green;}"><script>didRun = true;<' + '/script>');
+document.write(didRun ? "PASS" : "FAIL");
+</script>
+</span>
diff --git a/LayoutTests/fast/tokenizer/inline-script-stylesheet.html b/LayoutTests/fast/tokenizer/inline-script-stylesheet.html
new file mode 100644 (file)
index 0000000..3fcdf4f
--- /dev/null
@@ -0,0 +1,11 @@
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<link rel=stylesheet href="data:text/css,span{color:green;}">
+Test that inline script blocks on stylesheet load:
+<span>
+<script>
+document.write(document.styleSheets[0] ? "PASS" : "FAIL");
+</script>
+</span>
index d6f2e43..cba0d7f 100644 (file)
@@ -5,4 +5,6 @@ main frame - didFinishLoadForFrame
 main frame - didCommitLoadForFrame
 didDisplayInsecureContent
 main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
 This test opens a window that loads an insecure style sheet. We should trigger a mixed content callback because the main frame in the window is HTTPS but is displaying insecure content.
index fd4ba4e..bd84d75 100644 (file)
@@ -11,9 +11,6 @@ layer at (0,0) size 800x600
           text run at (0,0) width 4: " "
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {DIV} at (0,41) size 784x0
-      RenderBlock (anonymous) at (0,41) size 784x0
-        RenderText {#text} at (0,0) size 0x0
-        RenderText {#text} at (0,0) size 0x0
 layer at (13,13) size 119x13
   RenderBlock {DIV} at (3,3) size 119x13
 caret: position 0 of child 0 {DIV} of child 1 {INPUT} of child 1 {DIV} of body
index 1d7c0da..5bd7435 100644 (file)
@@ -1,3 +1,33 @@
+2010-12-31  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        Scripts should not be executed before preceding stylesheets are loaded
+        https://bugs.webkit.org/show_bug.cgi?id=8852
+
+        Block inline script execution on pending stylesheet loads. This matches
+        other browsers and HTML5.
+
+        Tests: fast/tokenizer/inline-script-stylesheet-write.html
+               fast/tokenizer/inline-script-stylesheet.html
+
+        * dom/PendingScript.cpp:
+        (WebCore::PendingScript::releaseElementAndClear):
+        * dom/PendingScript.h:
+        (WebCore::PendingScript::PendingScript):
+        (WebCore::PendingScript::operator=):
+        (WebCore::PendingScript::startingPosition):
+        (WebCore::PendingScript::setStartingPosition):
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::process):
+        
+        This fixes an unrelated bug with beforeload events that was exposed by the other
+        changes (fast/dom/beforeload/remove-link-in-beforeload-listener.html).
+        
+        * html/parser/HTMLScriptRunner.cpp:
+        (WebCore::HTMLScriptRunner::sourceFromPendingScript):
+        (WebCore::HTMLScriptRunner::runScript):
+
 2011-01-04  Xianzhu Wang  <wangxianzhu@google.com>
 
         Reviewed by Darin Adler.
index 10b8137..615fa7d 100644 (file)
@@ -41,6 +41,7 @@ PassRefPtr<Element> PendingScript::releaseElementAndClear()
 {
     setCachedScript(0);
     m_watchingForLoad = false;
+    m_startingPosition = TextPosition1::belowRangePosition();
     return m_element.release();
 }
 
index f679d5d..9c4c48b 100644 (file)
@@ -45,6 +45,7 @@ class PendingScript : public CachedResourceClient {
 public:
     PendingScript()
         : m_watchingForLoad(false)
+        , m_startingPosition(TextPosition1::belowRangePosition())
     {
     }
 
@@ -52,6 +53,7 @@ public:
         : CachedResourceClient(other)
         , m_watchingForLoad(other.m_watchingForLoad)
         , m_element(other.m_element)
+        , m_startingPosition(other.m_startingPosition)
     {
         setCachedScript(other.cachedScript());
     }
@@ -65,11 +67,15 @@ public:
 
         m_watchingForLoad = other.m_watchingForLoad;
         m_element = other.m_element;
+        m_startingPosition = other.m_startingPosition;
         setCachedScript(other.cachedScript());
 
         return *this;
     }
 
+    TextPosition1 startingPosition() const { return m_startingPosition; }
+    void setStartingPosition(const TextPosition1& position) { m_startingPosition = position; }
+
     bool watchingForLoad() const { return m_watchingForLoad; }
     void setWatchingForLoad(bool b) { m_watchingForLoad = b; }
 
@@ -85,7 +91,8 @@ public:
 private:
     bool m_watchingForLoad;
     RefPtr<Element> m_element;
-    CachedResourceHandle<CachedScript> m_cachedScript;
+    TextPosition1 m_startingPosition; // Only used for inline script tags.
+    CachedResourceHandle<CachedScript> m_cachedScript; 
 };
 
 }
index c71544f..fc29d1d 100644 (file)
@@ -237,9 +237,13 @@ void HTMLLinkElement::process()
             m_cachedSheet = 0;
         }
 
+        RefPtr<Document> originalDocument = document();
         if (!dispatchBeforeLoadEvent(m_url))
             return;
-        
+        // A beforeload handler might have removed us from the document or changed the document.
+        if (!inDocument() || document() != originalDocument)
+            return;
+
         m_loading = true;
 
         bool mediaQueryMatches = true;
index 2672f39..5e70546 100644 (file)
@@ -99,7 +99,7 @@ ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript&
         return ScriptSourceCode(script.cachedScript());
     }
     errorOccurred = false;
-    return ScriptSourceCode(script.element()->textContent(), documentURLForScriptExecution(m_document));
+    return ScriptSourceCode(script.element()->textContent(), documentURLForScriptExecution(m_document), script.startingPosition());
 }
 
 bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script)
@@ -303,11 +303,14 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition1& scriptSta
                 requestDeferredScript(script);
             else
                 requestParsingBlockingScript(script);
+        } else if (!m_document->haveStylesheetsLoaded() && m_scriptNestingLevel == 1) {
+            // Block inline script execution on stylesheet load, unless we are in document.write().
+            // The latter case can only happen if a script both triggers a stylesheet load
+            // and writes an inline script. Since write is blocking we have to execute the
+            // written script immediately, ignoring the pending sheets.
+            m_parsingBlockingScript.adoptElement(script);
+            m_parsingBlockingScript.setStartingPosition(scriptStartPosition);
         } 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);