WebCore:
authorandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Jun 2006 20:35:12 +0000 (20:35 +0000)
committerandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Jun 2006 20:35:12 +0000 (20:35 +0000)
2006-06-21  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Geoff.

        http://bugzilla.opendarwin.org/show_bug.cgi?id=6058
        XMLTokenizer runs all <script> tags at once instead of as they're encountered

        * dom/xml_tokenizer.cpp:
        (WebCore::XMLTokenizer::XMLTokenizer):
        Initialize new members.

        (WebCore::XMLTokenizer::endElementNs):
        If we've encountered a script tag, execute the script here. If the script
        tag refers to an external resource, pause the parser while loading it.

        (WebCore::XMLTokenizer::end):
        Move code from finish() to here

        (WebCore::XMLTokenizer::finish):
        Only call end() if the parser isn't paused.

        (WebCore::XMLTokenizer::notifyFinished):
        Evaluate the script here and resume the parser.

        (WebCore::XMLTokenizer::resumeParsing):
        If finish() was called, call end() after writing all data.

LayoutTests:

2006-06-21  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Geoff.

        http://bugzilla.opendarwin.org/show_bug.cgi?id=6058
        XMLTokenizer runs all <script> tags at once instead of as they're encountered

        * dom/svg/level3/xpath/svgunit.js:
        The XPath tests depend on the document being loaded before running the tests.
        Add a "load" event listener and run the test in the handler.

        * fast/canvas/quadraticCurveTo.xml:
        Add onload handler and run tests there.

        * fast/innerHTML/004-expected.txt:
        * fast/innerHTML/004.xhtml:
        Add load event listener and run test there.

        * fast/parser/external-entities-expected.txt:
        This now dumps as text because the script is ran before the parse error is encountered.

        * fast/parser/resources/xhtml-scripts.js: Added.
        * fast/parser/xhtml-scripts-expected.txt: Added.
        * fast/parser/xhtml-scripts.xhtml: Added.
        Add new tests.

        * svg/custom/text-hit-test.svg:
        Run test in onload handler.

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/dom/svg/level3/xpath/svgunit.js
LayoutTests/fast/canvas/quadraticCurveTo.xml
LayoutTests/fast/innerHTML/004-expected.txt
LayoutTests/fast/innerHTML/004.xhtml
LayoutTests/fast/parser/external-entities-expected.txt
LayoutTests/fast/parser/resources/xhtml-scripts.js [new file with mode: 0644]
LayoutTests/fast/parser/xhtml-scripts-expected.txt [new file with mode: 0644]
LayoutTests/fast/parser/xhtml-scripts.xhtml [new file with mode: 0644]
LayoutTests/svg/custom/text-hit-test.svg
WebCore/ChangeLog
WebCore/dom/xml_tokenizer.cpp

index 7a3abcd97cf65477e83353bfb03ec43fd98c2bfd..7d39dc8c32704ddbc2e232cdc0b00d567ee455ff 100644 (file)
@@ -1,3 +1,32 @@
+2006-06-21  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Geoff.
+
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=6058
+        XMLTokenizer runs all <script> tags at once instead of as they're encountered
+
+        * dom/svg/level3/xpath/svgunit.js:
+        The XPath tests depend on the document being loaded before running the tests.
+        Add a "load" event listener and run the test in the handler.
+        
+        * fast/canvas/quadraticCurveTo.xml:
+        Add onload handler and run tests there.
+        
+        * fast/innerHTML/004-expected.txt:
+        * fast/innerHTML/004.xhtml:
+        Add load event listener and run test there.
+        
+        * fast/parser/external-entities-expected.txt:
+        This now dumps as text because the script is ran before the parse error is encountered.
+        
+        * fast/parser/resources/xhtml-scripts.js: Added.
+        * fast/parser/xhtml-scripts-expected.txt: Added.
+        * fast/parser/xhtml-scripts.xhtml: Added.
+        Add new tests.
+        
+        * svg/custom/text-hit-test.svg:
+        Run test in onload handler.
+        
 2006-06-20  Maciej Stachowiak  <mjs@apple.com>
 
         No review - updated results for earlier patch.
index fa7f3695b8a4b4f55583adce0733b0281f33056c..12f03786ccecda77e0845df1dda3bdd6893d2859 100644 (file)
@@ -674,22 +674,26 @@ function getResourceURI(name, scheme, contentType) {
     return base + name + getSuffix(contentType);
 }
 
-
-//
-//   invoke test setup
-//
-setUpPage();
-
-try {
-       runTest();
-       if (builder.initializationError == null) {
-          changeColor("green");
-          addMessage("0", "120", exposeTestFunctionNames()[0] + ": Success");
-       } else {
+function onloadHandler() {
+       //
+       //   invoke test setup
+       //
+       setUpPage();
+
+       try {
+               runTest();
+               if (builder.initializationError == null) {
+                       changeColor("green");
+                       addMessage("0", "120", exposeTestFunctionNames()[0] + ": Success");
+               } else {
+                       addMessage("0", "120", exposeTestFunctionNames()[0]);
+               }
+       } catch(ex) {
                addMessage("0", "120", exposeTestFunctionNames()[0]);
-       }
-} catch(ex) {
-       addMessage("0", "120", exposeTestFunctionNames()[0]);
-    changeColor("red");
-    addMessage("0", "140", ex);    
-}
\ No newline at end of file
+       changeColor("red");
+       addMessage("0", "140", ex);    
+       }       
+}
+// Add loader
+window.addEventListener('load', onloadHandler, false)
+
index dd52f6ae3e9d3e0b6d538e407e0ef9f5c09b7ffd..369fec1dd9f9e0e89a63ee3e87e29f8feff69fb4 100644 (file)
                        }
 
                        ////////////////////
+            
+            function runTest() {
+                           // setup canvas and context
+                           var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
+                           canvas.setAttribute('width', 480);
+                           canvas.setAttribute('height', 360);
+                           document.documentElement.appendChild(canvas);
+                           ctx = canvas.getContext('2d');
 
-                       // setup canvas and context
-                       var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
-                       canvas.setAttribute('width', 480);
-                       canvas.setAttribute('height', 360);
-                       document.documentElement.appendChild(canvas);
-                       ctx = canvas.getContext('2d');
-
-                       // draw shapes equivalent to SVG path data "M 240 296 q 25 -100 47 0 t 47 0 t 47 0 t 47 0 t 47 0 z"
-                       M(10,60);
-                       q(25,-100,47,0);
-                       t(47,0);
-                       t(47,0);
-                       t(47,0);
-                       t(47,0);
-                       z();
-
-                       // stroke it
-                       ctx.stroke();
+                           // draw shapes equivalent to SVG path data "M 240 296 q 25 -100 47 0 t 47 0 t 47 0 t 47 0 t 47 0 z"
+                           M(10,60);
+                           q(25,-100,47,0);
+                           t(47,0);
+                           t(47,0);
+                           t(47,0);
+                           t(47,0);
+                           z();
 
+                           // stroke it
+                           ctx.stroke();
+            }
                </script>
        </head>
 
-       <body>
+       <body onload="runTest()">
 
                <p>
                        This test case should produce a sine-wave stroked with 1px black.   
index b82c0fad6bd2b3a1859e940f71e16290b97de1bc..612f26ed528f44de40984f2e8e284ceb13dd5da7 100644 (file)
@@ -17,9 +17,12 @@ Content:
   <circle cx="150" cy="100" r="50" xlink:title="test"/>
 </svg>
 <script>
-if (window.layoutTestController)
-       layoutTestController.dumpAsText();
-document.getElementById("content").firstChild.nodeValue = document.documentElement.innerHTML;
+window.addEventListener ("load", function() {
+    if (window.layoutTestController)
+           layoutTestController.dumpAsText();
+    document.getElementById("content").firstChild.nodeValue = document.documentElement.innerHTML;
+}, false);
+
 </script>
 </body>
 test 
index 019cec5e1de5c1d321f3974824fc5ddf714c702d..40e199e17c7dbc1e6003ff3d8d973f7126e5b762 100644 (file)
   <circle cx="150" cy="100" r="50" xlink:title="test"/>
 </svg>
 <script>
-if (window.layoutTestController)
-       layoutTestController.dumpAsText();
-document.getElementById("content").firstChild.nodeValue = document.documentElement.innerHTML;
+window.addEventListener ("load", function() {
+    if (window.layoutTestController)
+           layoutTestController.dumpAsText();
+    document.getElementById("content").firstChild.nodeValue = document.documentElement.innerHTML;
+}, false);
+
 </script>
 </body>
 </html>
index 296d28583fd041cba7789dc4c43f723b3a2b3ec6..49ad3047078fb0d449fcebf408ca70142ffac7bc 100644 (file)
@@ -1,26 +1,8 @@
-layer at (0,0) size 800x600
-  RenderView at (0,0) size 800x600
-layer at (0,0) size 800x164
-  RenderBlock {html} at (0,0) size 800x164
-    RenderBlock (anonymous) at (0,0) size 800x0
-      RenderInline {parsererror} at (0,0) size 0x0 [bgcolor=#FFDDDD] [border: (2px solid #CC7777)]
-    RenderBlock (anonymous) at (0,18) size 800x94
-      RenderBlock {h3} at (0,0) size 800x22
-        RenderText {#text} at (0,0) size 324x22
-          text run at (0,0) width 324: "This page contains the following errors:"
-      RenderBlock {div} at (0,40) size 800x14
-        RenderText {#text} at (0,0) size 406x14
-          text run at (0,0) width 406: "error on line 9 at column 47: Entity 'message' not defined"
-          text run at (406,0) width 0: " "
-      RenderBlock {h3} at (0,72) size 800x22
-        RenderText {#text} at (0,0) size 429x22
-          text run at (0,0) width 429: "Below is a rendering of the page up to the first error."
-    RenderBlock (anonymous) at (0,130) size 800x0
-      RenderInline {parsererror} at (0,0) size 0x0 [bgcolor=#FFDDDD] [border: (2px solid #CC7777)]
-    RenderBody {body} at (8,130) size 784x18
-      RenderBlock {p} at (0,0) size 784x0
-      RenderBlock {p} at (0,0) size 784x18
-        RenderInline {font} at (0,0) size 489x18 [color=#FF0000]
-          RenderText {#text} at (0,0) size 489x18
-            text run at (0,0) width 263: "This should be the only line on this page. "
-            text run at (263,0) width 226: "You should see a parse error above."
+This page contains the following errors:
+
+error on line 9 at column 47: Entity 'message' not defined
+Below is a rendering of the page up to the first error.
+
+This should be the only line on this page. You should see a parse error above.
+
+
diff --git a/LayoutTests/fast/parser/resources/xhtml-scripts.js b/LayoutTests/fast/parser/resources/xhtml-scripts.js
new file mode 100644 (file)
index 0000000..696dfab
--- /dev/null
@@ -0,0 +1,5 @@
+// This shouldn't be known since we haven't parsed that far yet.
+var d = document.getElementById('div2');
+
+if (d)
+    failure = true;
diff --git a/LayoutTests/fast/parser/xhtml-scripts-expected.txt b/LayoutTests/fast/parser/xhtml-scripts-expected.txt
new file mode 100644 (file)
index 0000000..f506348
--- /dev/null
@@ -0,0 +1,3 @@
+This tests that parsing stops when a script is encountered in an XML document. Parsing resumes when the script has finished executing.
+SUCCESS
+
diff --git a/LayoutTests/fast/parser/xhtml-scripts.xhtml b/LayoutTests/fast/parser/xhtml-scripts.xhtml
new file mode 100644 (file)
index 0000000..2f10cf6
--- /dev/null
@@ -0,0 +1,29 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<body>
+    <script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+        
+    var failure = false;
+
+    // This shouldn't be known since we haven't parsed that far yet.
+    var d = document.getElementById('div1');
+
+    if (d)
+        failure = true;
+    </script>
+    
+    <div id="div1"/>
+    
+    <script src="resources/xhtml-scripts.js"/>
+    <div id="div2"/>
+    
+    This tests that parsing stops when a script is encountered in an XML document. Parsing resumes when the script has finished executing.
+    <div id="result">FAILURE</div>
+    
+    <script>
+        if (!failure)
+            document.getElementById('result').firstChild.nodeValue = 'SUCCESS';
+    </script>
+</body>
+</html>
index 352ba10361fdb045b427fc7891f66c86c87dd75b..23824178380fd85b22c78052fa18763530c69058 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd">
-<svg version="1.1" baseProfile="basic" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%">
+<svg version="1.1" baseProfile="basic" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" onload="runTest()">
    <script type="text/ecmascript"><![CDATA[
       var states = [];
       var clicked;
          }
          return true;
       }
-      if (window.eventSender) {
-         testClickAt(91*2, 71*2); 
-         testClickAt(91*2, 21*2); 
-         document.getElementById("status").textContent = "Failed";
-         if (checkResults())
-            document.getElementById("status").textContent = "Passed";
-      } else {
-         // in manual mode
-         alert("Please use run-webkit-tests.");
-      }
+      
+      function runTest() {
+         if (window.eventSender) {
+            testClickAt(91*2, 71*2); 
+            testClickAt(91*2, 21*2); 
+            document.getElementById("status").textContent = "Failed";
+            if (checkResults())
+                document.getElementById("status").textContent = "Passed";
+         } else {
+            // in manual mode
+            alert("Please use run-webkit-tests.");
+        }
+     }
    ]]></script>
    <g transform="scale(2)">
    <text x="70" y="70" onmousedown="clicked=true;">Click me</text>
index c1034d1750be2e369cb5d29c46d37c9682aade1b..91e976f19ac61b178984cb62befeecbb0836f166 100644 (file)
@@ -1,3 +1,30 @@
+2006-06-21  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Geoff.
+
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=6058
+        XMLTokenizer runs all <script> tags at once instead of as they're encountered
+        
+        * dom/xml_tokenizer.cpp:
+        (WebCore::XMLTokenizer::XMLTokenizer):
+        Initialize new members.
+        
+        (WebCore::XMLTokenizer::endElementNs):
+        If we've encountered a script tag, execute the script here. If the script
+        tag refers to an external resource, pause the parser while loading it.
+        
+        (WebCore::XMLTokenizer::end):
+        Move code from finish() to here
+        
+        (WebCore::XMLTokenizer::finish):
+        Only call end() if the parser isn't paused.
+        
+        (WebCore::XMLTokenizer::notifyFinished):
+        Evaluate the script here and resume the parser.
+        
+        (WebCore::XMLTokenizer::resumeParsing):
+        If finish() was called, call end() after writing all data.
+
 2006-06-21  Steve Falkenburg  <sfalken@apple.com>
 
         Fix build break
index c405e796b73bac8ab39c06b1cc62ad78bd323983..6a7825f236d76ebae850357776122a8711a3aec8 100644 (file)
@@ -32,6 +32,7 @@
 #include "Document.h"
 #include "DocumentFragment.h"
 #include "DocumentType.h"
+#include "EventNames.h"
 #include "Frame.h"
 #include "HTMLNames.h"
 #include "HTMLScriptElement.h"
@@ -52,7 +53,8 @@
 using namespace std;
 
 namespace WebCore {
-    
+
+using namespace EventNames;
 using namespace HTMLNames;
 
 const int maxErrors = 25;
@@ -76,6 +78,8 @@ public:
     virtual bool isWaitingForScripts() const;
     virtual void stopParsing();
 
+    void end();
+
     void pauseParsing();
     void resumeParsing();
     
@@ -106,9 +110,6 @@ private:
 
     void insertErrorMessageBlock();
 
-    void executeScripts();
-    void addScripts(Node *n);
-
     bool enterText();
     void exitText();
 
@@ -127,15 +128,16 @@ private:
     bool m_isXHTMLDocument;
     
     bool m_parserPaused;
+    bool m_requestingScript;
+    bool m_finishCalled;
     
     int m_errorCount;
     int m_lastErrorLine;
     int m_lastErrorColumn;
     String m_errorMessages;
 
-    DeprecatedPtrList<Element> m_scripts;
-    DeprecatedPtrListIterator<Element> *m_scriptsIt;
-    CachedScript *m_cachedScript;
+    CachedScript *m_pendingScript;
+    RefPtr<Element> m_scriptElement;
     
     bool m_parsingFragment;
     String m_defaultNamespaceURI;
@@ -520,11 +522,12 @@ XMLTokenizer::XMLTokenizer(Document *_doc, FrameView *_view)
     , m_sawFirstElement(false)
     , m_isXHTMLDocument(false)
     , m_parserPaused(false)
+    , m_requestingScript(false)
+    , m_finishCalled(false)
     , m_errorCount(0)
     , m_lastErrorLine(0)
     , m_lastErrorColumn(0)
-    , m_scriptsIt(0)
-    , m_cachedScript(0)
+    , m_pendingScript(0)
     , m_parsingFragment(false)
     , m_pendingCallbacks(new PendingCallbacks)
 {
@@ -541,11 +544,12 @@ XMLTokenizer::XMLTokenizer(DocumentFragment *fragment, Element *parentElement)
     , m_sawFirstElement(false)
     , m_isXHTMLDocument(false)
     , m_parserPaused(false)
+    , m_requestingScript(false)
+    , m_finishCalled(false)
     , m_errorCount(0)
     , m_lastErrorLine(0)
     , m_lastErrorColumn(0)
-    , m_scriptsIt(0)
-    , m_cachedScript(0)
+    , m_pendingScript(0)
     , m_parsingFragment(true)
     , m_pendingCallbacks(new PendingCallbacks)
 {
@@ -583,9 +587,8 @@ XMLTokenizer::~XMLTokenizer()
     if (m_parsingFragment && m_doc)
         m_doc->deref();
     delete m_pendingCallbacks;
-    delete m_scriptsIt;
-    if (m_cachedScript)
-        m_cachedScript->deref(this);
+    if (m_pendingScript)
+        m_pendingScript->deref(this);
 }
 
 void XMLTokenizer::setCurrentNode(Node* n)
@@ -782,6 +785,56 @@ void XMLTokenizer::endElementNs()
         n = n->parentNode();
     RefPtr<Node> parent = n->parentNode();
     n->closeRenderer();
+    
+    // don't load external scripts for standalone documents (for now)
+    if (n->isElementNode() && m_view && (static_cast<Element*>(n)->hasTagName(scriptTag) 
+#if SVG_SUPPORT
+                                         || static_cast<Element*>(n)->hasTagName(SVGNames::scriptTag)
+#endif
+                                         )) {
+
+                                         
+        ASSERT(!m_pendingScript);
+        
+        m_requestingScript = true;
+        
+        Element* scriptElement = static_cast<Element*>(n);        
+        String scriptHref;
+        
+        if (static_cast<Element*>(n)->hasTagName(scriptTag))
+            scriptHref = scriptElement->getAttribute(srcAttr);
+#if SVG_SUPPORT
+        else if (static_cast<Element*>(n)->hasTagName(SVGNames::scriptTag))
+            scriptHref = scriptElement->getAttribute(XLinkNames::hrefAttr);
+#endif
+        
+        if (!scriptHref.isEmpty()) {
+            // we have a src attribute 
+            DeprecatedString charset = scriptElement->getAttribute(charsetAttr).deprecatedString();
+            
+            if ((m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, charset))) {
+                m_scriptElement = scriptElement;
+                m_pendingScript->ref(this);
+                    
+                // m_pendingScript will be 0 if script was already loaded and ref() executed it
+                if (m_pendingScript)
+                    pauseParsing();
+            } else 
+                m_scriptElement = 0;
+
+        } else {
+            DeprecatedString scriptCode = "";
+            for (Node *child = scriptElement->firstChild(); child; child = child->nextSibling()) {
+                if (child->isTextNode() || child->nodeType() == Node::CDATA_SECTION_NODE)
+                    scriptCode += static_cast<CharacterData*>(child)->data().deprecatedString();
+            }
+                
+            m_view->frame()->executeScript(0, scriptCode);
+        }
+        
+        m_requestingScript = false;
+    }
+
     setCurrentNode(parent.get());
 }
 
@@ -1124,7 +1177,7 @@ void XMLTokenizer::initializeParserContext()
     m_context = createQStringParser(&sax, this);
 }
 
-void XMLTokenizer::finish()
+void XMLTokenizer::end()
 {
     if (m_sawXSLTransform) {
         m_doc->setTransformSource(xmlDocPtrForString(m_originalSourceForTransform, m_doc->URL()));
@@ -1134,7 +1187,7 @@ void XMLTokenizer::finish()
         m_doc->setParsing(true);
         m_parserStopped = true;
     }
-        
+    
     if (m_context) {
         // Tell libxml we're done.
         xmlParseChunk(m_context, 0, 0, 1);
@@ -1148,16 +1201,20 @@ void XMLTokenizer::finish()
     if (m_sawError)
         insertErrorMessageBlock();
     else {
-        // Parsing was successful. Now locate all html <script> tags in the document and execute them
-        // one by one.
         exitText();
-        addScripts(m_doc);
-        m_scriptsIt = new DeprecatedPtrListIterator<Element>(m_scripts);
-        executeScripts();
+        m_doc->updateStyleSelector();
     }
     
     setCurrentNode(0);
-    m_doc->finishedParsing();
+    m_doc->finishedParsing();    
+}
+
+void XMLTokenizer::finish()
+{
+    if (m_parserPaused)
+        m_finishCalled = true;
+    else
+        end();
 }
 
 static inline RefPtr<Element> createXHTMLParserErrorHeader(Document* doc, const String& errorMessages) 
@@ -1226,80 +1283,36 @@ void XMLTokenizer::insertErrorMessageBlock()
     doc->updateRendering();
 }
 
-void XMLTokenizer::addScripts(Node *n)
-{
-    // Recursively go through the entire document tree, looking for html <script> tags. For each of these
-    // that is found, add it to the m_scripts list from which they will be executed
-    if (n->hasTagName(scriptTag)
-#if SVG_SUPPORT
-        || n->hasTagName(WebCore::SVGNames::scriptTag)
-#endif
-        )
-        m_scripts.append(static_cast<Element*>(n));
-
-    Node *child;
-    for (child = n->firstChild(); child; child = child->nextSibling())
-        addScripts(child);
-}
-
-void XMLTokenizer::executeScripts()
-{
-    // Iterate through all of the html <script> tags in the document. For those that have a src attribute,
-    // start loading the script and return (executeScripts() will be called again once the script is loaded
-    // and continue where it left off). For scripts that don't have a src attribute, execute the code
-    // inside the tag
-    while (Element *scriptElement = m_scriptsIt->current()) {
-        ++(*m_scriptsIt);
-        String scriptHref = scriptElement->getAttribute(srcAttr);
-#if SVG_SUPPORT
-        if (scriptElement->hasTagName(WebCore::SVGNames::scriptTag))
-            scriptHref = scriptElement->getAttribute(XLinkNames::hrefAttr);
-#endif
-        // don't load external scripts for standalone documents (for now)
-        if (!scriptHref.isEmpty() && m_doc->frame()) {
-            // we have a src attribute
-            DeprecatedString charset = scriptElement->getAttribute(charsetAttr).deprecatedString();
-            m_cachedScript = m_doc->docLoader()->requestScript(scriptHref, charset);
-            m_cachedScript->ref(this); // will call executeScripts() again if already cached
-            return;
-        } else {
-            // no src attribute - execute from contents of tag
-            DeprecatedString scriptCode = "";
-            for (Node *child = scriptElement->firstChild(); child; child = child->nextSibling()) {
-                if (child->isTextNode() || child->nodeType() == Node::CDATA_SECTION_NODE)
-                    scriptCode += static_cast<CharacterData*>(child)->data().deprecatedString();
-            }
-            // the script cannot do document.write until we support incremental parsing
-            // ### handle the case where the script deletes the node or redirects to
-            // another page, etc. (also in notifyFinished())
-            // ### the script may add another script node after this one which should be executed
-            if (m_view)
-                m_view->frame()->executeScript(0, scriptCode);
-        }
-    }
-
-    // All scripts have finished executing, so calculate the style for the document and close
-    // the last element
-    m_doc->updateStyleSelector();
-}
-
 void XMLTokenizer::notifyFinished(CachedObject *finishedObj)
 {
-    // This is called when a script has finished loading that was requested from executeScripts(). We execute
-    // the script, and then call executeScripts() again to continue iterating through the list of scripts in
-    // the document
-    if (finishedObj == m_cachedScript) {
-        String scriptSource = m_cachedScript->script();
-        m_cachedScript->deref(this);
-        m_cachedScript = 0;
-        m_view->frame()->executeScript(0, scriptSource.deprecatedString());
-        executeScripts();
+    ASSERT(m_pendingScript == finishedObj);
+    ASSERT(m_pendingScript->accessCount() > 0);
+        
+    String cachedScriptUrl = m_pendingScript->url();
+    String scriptSource = m_pendingScript->script();
+    bool errorOccurred = m_pendingScript->errorOccurred();
+    m_pendingScript->deref(this);
+    m_pendingScript = 0;
+    
+    RefPtr<Element> e = m_scriptElement;
+    m_scriptElement = 0;
+    
+    if (errorOccurred) 
+        EventTargetNodeCast(e.get())->dispatchHTMLEvent(errorEvent, true, false);
+    else {
+        m_view->frame()->executeScript(cachedScriptUrl, 0, 0, scriptSource.deprecatedString());
+        EventTargetNodeCast(e.get())->dispatchHTMLEvent(loadEvent, false, false);
     }
+    
+    m_scriptElement = 0;
+    
+    if (!m_requestingScript)
+        resumeParsing();
 }
 
 bool XMLTokenizer::isWaitingForScripts() const
 {
-    return m_cachedScript != 0;
+    return m_pendingScript != 0;
 }
 
 #ifdef KHTML_XSLT
@@ -1369,6 +1382,10 @@ void XMLTokenizer::resumeParsing()
     SegmentedString rest = m_pendingSrc;
     m_pendingSrc.clear();
     write(rest, false);
+    
+    // Finally, if finish() has been called, call end()
+    if (m_finishCalled)
+        end();
 }
 
 static void balancedStartElementNsHandler(void *closure, const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **libxmlAttributes)