Reviewed by Darin, landed by ap.
authorap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Dec 2005 18:46:24 +0000 (18:46 +0000)
committerap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Dec 2005 18:46:24 +0000 (18:46 +0000)
        Test: fast/dom/HTMLScriptElement/script-load-events.html

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=5812
          Generate load events for <script> elements

        * khtml/html/html_headimpl.cpp:
        (HTMLScriptElementImpl::parseMappedAttribute): Parse the onload and onerror attributes.
        (HTMLScriptElementImpl::closeRenderer): Call base class's implementation.
        (HTMLScriptElementImpl::notifyFinished): Dispatch load and error events.
        * khtml/html/htmlparser.h:
        * khtml/html/htmlparser.cpp:
        (HTMLParser::parseToken): Return the node that was inserted.
        * khtml/html/htmltokenizer.h: Added scriptNode, a RefPtr to the node corresponding
        to the current load request.
        * khtml/html/htmltokenizer.cpp:
        (HTMLTokenizer::scriptHandler): Reset scriptNode if a load request was not made.
        (HTMLTokenizer::parseTag): Set scriptNode to the node created from the script tag.
        (HTMLTokenizer::processToken): Return the node that was inserted.
        (HTMLTokenizer::notifyFinished): Reset scriptNode and dispatch load and error events.
        * khtml/misc/loader.h:
        (CachedScript::errorOccurred): Added.
        * khtml/misc/loader.cpp:
        (CachedScript::CachedScript):
        (CachedScript::error):

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

WebCore/ChangeLog
WebCore/khtml/html/html_headimpl.cpp
WebCore/khtml/html/htmlparser.cpp
WebCore/khtml/html/htmlparser.h
WebCore/khtml/html/htmltokenizer.cpp
WebCore/khtml/html/htmltokenizer.h
WebCore/khtml/misc/loader.cpp
WebCore/khtml/misc/loader.h

index 69d5503eacd1ac9b1e7501ce3951c5eb005872f7..60b333053ef981922e3dcce8cd9dd72552788922 100644 (file)
@@ -1,3 +1,32 @@
+2005-12-28  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Darin, landed by ap.
+
+        Test: fast/dom/HTMLScriptElement/script-load-events.html
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=5812
+          Generate load events for <script> elements
+
+        * khtml/html/html_headimpl.cpp:
+        (HTMLScriptElementImpl::parseMappedAttribute): Parse the onload and onerror attributes.
+        (HTMLScriptElementImpl::closeRenderer): Call base class's implementation.
+        (HTMLScriptElementImpl::notifyFinished): Dispatch load and error events.
+        * khtml/html/htmlparser.h:
+        * khtml/html/htmlparser.cpp:
+        (HTMLParser::parseToken): Return the node that was inserted.
+        * khtml/html/htmltokenizer.h: Added scriptNode, a RefPtr to the node corresponding
+        to the current load request.
+        * khtml/html/htmltokenizer.cpp:
+        (HTMLTokenizer::scriptHandler): Reset scriptNode if a load request was not made.
+        (HTMLTokenizer::parseTag): Set scriptNode to the node created from the script tag.
+        (HTMLTokenizer::processToken): Return the node that was inserted.
+        (HTMLTokenizer::notifyFinished): Reset scriptNode and dispatch load and error events.
+        * khtml/misc/loader.h:
+        (CachedScript::errorOccurred): Added.
+        * khtml/misc/loader.cpp:
+        (CachedScript::CachedScript):
+        (CachedScript::error):
+
 2005-12-28  Alexey Proskuryakov  <ap@nypop.com>
 
         Reviewed by Maciej.
index 7284f54d316e1fa2da705036f9f57406bab8566b..f1ad4418f7b2634ecfd4be16b8c19bc5d88b5feb 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "html/html_documentimpl.h"
 #include "xml/dom_textimpl.h"
+#include "xml/EventNames.h"
 
 #include "khtmlview.h"
 #include "khtml_part.h"
@@ -45,6 +46,7 @@
 
 using namespace DOM;
 using namespace HTMLNames;
+using namespace EventNames;
 using namespace khtml;
 
 HTMLBaseElementImpl::HTMLBaseElementImpl(DocumentImpl *doc)
@@ -507,7 +509,8 @@ void HTMLScriptElementImpl::childrenChanged()
 
 void HTMLScriptElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
 {
-    if (attr->name() == srcAttr) {
+    const QualifiedName& attrName = attr->name();
+    if (attrName == srcAttr) {
         if (m_evaluated || m_cachedScript || m_createdByParser || !inDocument())
             return;
 
@@ -522,6 +525,10 @@ void HTMLScriptElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
             m_cachedScript = getDocument()->docLoader()->requestScript(url, charset);
             m_cachedScript->ref(this);
         }
+    } else if (attrName == onerrorAttr) {
+        setHTMLEventListener(errorEvent, attr);
+    } else if (attrName == onloadAttr) {
+        setHTMLEventListener(loadEvent, attr);
     } else
         HTMLElementImpl::parseMappedAttribute(attr);
 }
@@ -532,6 +539,7 @@ void HTMLScriptElementImpl::closeRenderer()
     // allow dynamic loading later.
     if (getAttribute(srcAttr).isEmpty() && text().isEmpty())
         setCreatedByParser(false);
+    HTMLElementImpl::closeRenderer();
 }
 
 void HTMLScriptElementImpl::insertedIntoDocument()
@@ -581,7 +589,12 @@ void HTMLScriptElementImpl::notifyFinished(CachedObject* o)
 
     assert(cs == m_cachedScript);
 
-    evaluateScript(cs->url(), cs->script());
+    if (cs->errorOccurred())
+        dispatchHTMLEvent(errorEvent, false, false);
+    else {
+        evaluateScript(cs->url(), cs->script());
+        dispatchHTMLEvent(loadEvent, false, false);
+    }
 
     cs->deref(this);
     m_cachedScript = 0;
index d5bdac5abf35cf4da34622939343789f7731be8f..2cfc3cb6d9a8340a52088dc15b4bc4384a35d580 100644 (file)
@@ -180,7 +180,7 @@ void HTMLParser::setCurrent(DOM::NodeImpl *newCurrent)
     currentIsReferenced = newCurrentIsReferenced;
 }
 
-void HTMLParser::parseToken(Token *t)
+NodeImpl *HTMLParser::parseToken(Token *t)
 {
     if (!discard_until.isNull()) {
         if (t->tagName == discard_until && !t->beginTag)
@@ -188,7 +188,7 @@ void HTMLParser::parseToken(Token *t)
 
         // do not skip </iframe>
         if (!discard_until.isNull() || (current->localName() != t->tagName))
-            return;
+            return 0;
     }
 
     // Apparently some sites use </br> instead of <br>.  Be compatible with IE and Firefox and treat this like <br>.
@@ -197,7 +197,7 @@ void HTMLParser::parseToken(Token *t)
 
     if (!t->beginTag) {
         processCloseTag(t);
-        return;
+        return 0;
     }
 
     // ignore spaces, if we're not inside a paragraph or other inline code
@@ -210,7 +210,7 @@ void HTMLParser::parseToken(Token *t)
     NodeImpl *n = getNode(t);
     // just to be sure, and to catch currently unimplemented stuff
     if (!n)
-        return;
+        return 0;
 
     RefPtr<NodeImpl> protectNode(n);
 
@@ -240,7 +240,10 @@ void HTMLParser::parseToken(Token *t)
 
         if (form == n)
             form = 0;
+        
+        return 0;
     }
+    return n;
 }
 
 static bool isTableSection(NodeImpl* n)
index d71da7bf36cfe0f41eef5dc6a43bb669b5cdc5a0..df7ed0d3e6525d4f78bd5603a5db7f84f19066e6 100644 (file)
@@ -62,7 +62,7 @@ public:
     /**
      * parses one token delivered by the tokenizer
      */
-    void parseToken(khtml::Token *_t);
+    DOM::NodeImpl *parseToken(khtml::Token *_t);
     
     /**
      * tokenizer says it's not going to be sending us any more tokens
index 267824190a30dc5cb48f8d4d8b6c7d9733d0476b..f2ef63f4cc659fe20fa3ec056e53fad68400c0d3 100644 (file)
@@ -43,6 +43,7 @@
 #include "khtmlview.h"
 #include "khtml_part.h"
 #include "xml/dom_docimpl.h"
+#include "xml/EventNames.h"
 #include "css/csshelper.h"
 #include "ecma/kjs_proxy.h"
 #include <kcharsets.h>
@@ -53,6 +54,7 @@
 #include <stdlib.h>
 
 using namespace DOM::HTMLNames;
+using namespace DOM::EventNames;
 
 using DOM::AtomicString;
 using DOM::AttributeImpl;
@@ -66,6 +68,7 @@ using DOM::textAtom;
 using DOM::QualifiedName;
 using DOM::MappedAttributeImpl;
 using DOM::NamedMappedAttrMapImpl;
+using DOM::NodeImpl;
 
 #include "kentities.c"
 
@@ -385,6 +388,8 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
 #endif
             if ( (cs = parser->doc()->docLoader()->requestScript(scriptSrc, scriptSrcCharset) ))
                 pendingScripts.enqueue(cs);
+            else
+                scriptNode = 0;
         }
         scriptSrc=QString::null;
     }
@@ -394,6 +399,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
         kdDebug( 6036 ) << QString(scriptCode, scriptCodeSize) << endl;
         kdDebug( 6036 ) << "---END SCRIPT---" << endl;
 #endif
+        scriptNode = 0;
         // Parse scriptCode containing <script> info
         doScriptExec = true;
     }
@@ -1275,11 +1281,13 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(TokenizerString &src, State state)
                 }
             }
 
-            processToken();
+            NodeImpl *n = processToken();
 
             if (tagName == preTag) {
                 state.setDiscardLF(true); // Discard the first LF after we open a pre.
             } else if (tagName == scriptTag) {
+                assert(!scriptNode);
+                scriptNode = n;
                 if (beginTag) {
                     searchStopper = scriptEnd;
                     searchStopperLen = 8;
@@ -1663,7 +1671,7 @@ void HTMLTokenizer::finish()
         end(); // this actually causes us to be deleted
 }
 
-void HTMLTokenizer::processToken()
+NodeImpl *HTMLTokenizer::processToken()
 {
     KJSProxyImpl *jsProxy = (view && view->part()) ? view->part()->jScript() : 0L;    
     if (jsProxy)
@@ -1685,7 +1693,7 @@ void HTMLTokenizer::processToken()
         currToken.reset();
         if (jsProxy)
             jsProxy->setEventHandlerLineno(lineno+src.lineCount());
-        return;
+        return 0;
     }
 
     dest = buffer;
@@ -1712,15 +1720,17 @@ void HTMLTokenizer::processToken()
     }
     kdDebug( 6036 ) << endl;
 #endif
+    NodeImpl *n = 0;
     
     if (!m_parserStopped) {
         // pass the token over to the parser, the parser DOES NOT delete the token
-        parser->parseToken(&currToken);
+        n = parser->parseToken(&currToken);
     }
     
     currToken.reset();
     if (jsProxy)
         jsProxy->setEventHandlerLineno(0);
+    return n;
 }
 
 HTMLTokenizer::~HTMLTokenizer()
@@ -1773,14 +1783,22 @@ void HTMLTokenizer::notifyFinished(CachedObject */*finishedObj*/)
         // make sure we forget about the script before we execute the new one
         // infinite recursion might happen otherwise
         QString cachedScriptUrl( cs->url().qstring() );
+        bool errorOccurred = cs->errorOccurred();
         cs->deref(this);
+        RefPtr<NodeImpl> n = scriptNode;
+        scriptNode = 0;
 
 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
         if (!parser->doc()->ownerElement())
             printf("external script beginning execution at %d\n", parser->doc()->elapsedTime());
 #endif
 
-       m_state = scriptExecution(scriptSource.qstring(), m_state, cachedScriptUrl);
+       if (errorOccurred)
+            n->dispatchHTMLEvent(errorEvent, false, false);
+        else {
+            m_state = scriptExecution(scriptSource.qstring(), m_state, cachedScriptUrl);
+            n->dispatchHTMLEvent(loadEvent, false, false);
+        }
 
         // The state of pendingScripts.isEmpty() can change inside the scriptExecution()
         // call above, so test afterwards.
index 60462bd619a5a6a877bf83911871d86a417912df..80c14534a91a56cc5bbcee2b99fd4167a7c5edd5 100644 (file)
@@ -112,7 +112,7 @@ protected:
     void end();
 
     void reset();
-    void processToken();
+    DOM::NodeImpl *processToken();
 
     State processListing(TokenizerString, State);
     State parseComment(TokenizerString&, State);
@@ -324,6 +324,7 @@ protected:
     // the output of the script to be postponed until after the script has finished executing
     int m_executingScript;
     QPtrQueue<CachedScript> pendingScripts;
+    RefPtr<DOM::NodeImpl> scriptNode;
     // you can pause the tokenizer if you need to display a dialog or something
     bool onHold;
 
index 99fb099ef6995f7cd9c827acd6c69575b6c40088..b9b8d1f0580be1b3a5c3104d6d9521c7dd59ae0b 100644 (file)
@@ -253,6 +253,7 @@ CachedScript::CachedScript(DocLoader* dl, const DOMString &url, KIO::CacheContro
     // But some websites think their scripts are <some wrong mimetype here>
     // and refuse to serve them if we only accept application/x-javascript.
     setAccept( QString::fromLatin1("*/*") );
+    m_errorOccurred = false;
     // load the file
     Cache::loader()->load(dl, this, false);
     m_loading = true;
@@ -265,6 +266,7 @@ CachedScript::CachedScript(DocLoader* dl, const DOMString &url, KIO::CacheContro
 CachedScript::CachedScript(const DOMString &url, const QString &script_data)
     : CachedObject(url, Script, KIO::CC_Verify, 0, script_data.length())
 {
+    m_errorOccurred = false;
     m_loading = false;
     m_status = Persistent;
     m_codec = 0;
@@ -323,6 +325,7 @@ void CachedScript::checkNotify()
 void CachedScript::error( int /*err*/, const char */*text*/ )
 {
     m_loading = false;
+    m_errorOccurred = true;
     checkNotify();
 }
 
index d6eb1a03892d334096bf88ac6f51e8226869ad94..5b32a0d2f12aa8ba5fdc3ac6cefa62fc66f2527f 100644 (file)
@@ -293,12 +293,15 @@ namespace khtml
        virtual void error( int err, const char *text );
 
         virtual bool schedule() const { return false; }
+        
+        bool errorOccurred() const { return m_errorOccurred; }
 
        void checkNotify();
 
     protected:
        DOM::DOMString m_script;
         QTextCodec* m_codec;
+        bool m_errorOccurred;
     };
 
     class ImageSource;