Title: [93380] trunk/Source/WebCore
Revision
93380
Author
[email protected]
Date
2011-08-18 18:09:34 -0700 (Thu, 18 Aug 2011)

Log Message

New XML parser: scripting support
https://bugs.webkit.org/show_bug.cgi?id=66406

Reviewed by Adam Barth.

* xml/parser/NewXMLDocumentParser.cpp:
(WebCore::NewXMLDocumentParser::NewXMLDocumentParser):
(WebCore::NewXMLDocumentParser::resumeParsing):
(WebCore::NewXMLDocumentParser::processScript):
(WebCore::NewXMLDocumentParser::append): Add support for pausing the parsing
(WebCore::NewXMLDocumentParser::finish): Add support for pausing the parsing
(WebCore::NewXMLDocumentParser::notifyFinished):
* xml/parser/NewXMLDocumentParser.h:
(WebCore::NewXMLDocumentParser::pauseParsing):
* xml/parser/XMLTreeBuilder.cpp: Add a shared function between self-closing and end tags
(WebCore::XMLTreeBuilder::closeElement): Registers scripts and pops the stack
(WebCore::XMLTreeBuilder::processStartTag):
(WebCore::XMLTreeBuilder::processEndTag):
* xml/parser/XMLTreeBuilder.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (93379 => 93380)


--- trunk/Source/WebCore/ChangeLog	2011-08-19 01:04:12 UTC (rev 93379)
+++ trunk/Source/WebCore/ChangeLog	2011-08-19 01:09:34 UTC (rev 93380)
@@ -1,3 +1,25 @@
+2011-08-18  Jeffrey Pfau  <[email protected]>
+
+        New XML parser: scripting support
+        https://bugs.webkit.org/show_bug.cgi?id=66406
+
+        Reviewed by Adam Barth.
+
+        * xml/parser/NewXMLDocumentParser.cpp:
+        (WebCore::NewXMLDocumentParser::NewXMLDocumentParser):
+        (WebCore::NewXMLDocumentParser::resumeParsing):
+        (WebCore::NewXMLDocumentParser::processScript):
+        (WebCore::NewXMLDocumentParser::append): Add support for pausing the parsing
+        (WebCore::NewXMLDocumentParser::finish): Add support for pausing the parsing
+        (WebCore::NewXMLDocumentParser::notifyFinished):
+        * xml/parser/NewXMLDocumentParser.h:
+        (WebCore::NewXMLDocumentParser::pauseParsing):
+        * xml/parser/XMLTreeBuilder.cpp: Add a shared function between self-closing and end tags
+        (WebCore::XMLTreeBuilder::closeElement): Registers scripts and pops the stack
+        (WebCore::XMLTreeBuilder::processStartTag):
+        (WebCore::XMLTreeBuilder::processEndTag):
+        * xml/parser/XMLTreeBuilder.h:
+
 2011-08-18  Mark Hahnenberg  <[email protected]>
 
         Move allocation in constructors into separate constructorBody() methods

Modified: trunk/Source/WebCore/xml/parser/NewXMLDocumentParser.cpp (93379 => 93380)


--- trunk/Source/WebCore/xml/parser/NewXMLDocumentParser.cpp	2011-08-19 01:04:12 UTC (rev 93379)
+++ trunk/Source/WebCore/xml/parser/NewXMLDocumentParser.cpp	2011-08-19 01:09:34 UTC (rev 93380)
@@ -27,6 +27,8 @@
 #include "NewXMLDocumentParser.h"
 
 #include "DocumentFragment.h"
+#include "ScriptElement.h"
+#include "ScriptSourceCode.h"
 #include "SegmentedString.h"
 #include "XMLTreeBuilder.h"
 
@@ -35,7 +37,10 @@
 NewXMLDocumentParser::NewXMLDocumentParser(Document* document)
     : ScriptableDocumentParser(document)
     , m_tokenizer(XMLTokenizer::create())
+    , m_parserPaused(false)
     , m_finishWasCalled(false)
+    , m_pendingScript(0)
+    , m_scriptElement(0)
     , m_treeBuilder(XMLTreeBuilder::create(this, document))
 {
 }
@@ -43,7 +48,10 @@
 NewXMLDocumentParser::NewXMLDocumentParser(DocumentFragment* fragment, Element* parent, FragmentScriptingPermission)
     : ScriptableDocumentParser(fragment->document())
     , m_tokenizer(XMLTokenizer::create())
+    , m_parserPaused(false)
     , m_finishWasCalled(false)
+    , m_pendingScript(0)
+    , m_scriptElement(0)
     , m_treeBuilder(XMLTreeBuilder::create(this, fragment, parent))
 {
 }
@@ -67,6 +75,30 @@
 {
 }
 
+void NewXMLDocumentParser::resumeParsing()
+{
+    m_parserPaused = false;
+    append(m_input);
+}
+
+void NewXMLDocumentParser::processScript(ScriptElement* scriptElement)
+{
+    if (scriptElement->prepareScript(TextPosition1(), ScriptElement::AllowLegacyTypeInTypeAttribute)) {
+        if (scriptElement->readyToBeParserExecuted())
+            scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), TextPosition1()));
+        else if (scriptElement->willBeParserExecuted()) {
+            m_pendingScript = scriptElement->cachedScript();
+            m_scriptElement = scriptElement->element();
+            m_pendingScript->addClient(this);
+
+            // m_pendingScript will be 0 if script was already loaded and addClient() executed it.
+            if (m_pendingScript)
+                pauseParsing();
+        } else
+            m_scriptElement = 0;
+    }
+}
+
 TextPosition0 NewXMLDocumentParser::textPosition() const
 {
     return TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(0),
@@ -85,9 +117,9 @@
 
 void NewXMLDocumentParser::append(const SegmentedString& string)
 {
-    SegmentedString input = string;
-    while (!input.isEmpty()) {
-        if (!m_tokenizer->nextToken(input, m_token))
+    m_input = string;
+    while (!m_input.isEmpty() && isParsing() && !m_parserPaused) {
+        if (!m_tokenizer->nextToken(m_input, m_token))
             continue;
 
 #ifndef NDEBUG
@@ -97,7 +129,7 @@
         AtomicXMLToken token(m_token);
         m_treeBuilder->processToken(token);
 
-        if (m_token.type() == XMLTokenTypes::EndOfFile || !isParsing())
+        if (m_token.type() == XMLTokenTypes::EndOfFile)
             break;
 
         m_token.clear();
@@ -108,8 +140,11 @@
 void NewXMLDocumentParser::finish()
 {
     ASSERT(!m_finishWasCalled);
+
+    if (m_parserPaused)
+        return;
+
     m_finishWasCalled = true;
-
     if (isParsing())
         prepareToStopParsing();
     document()->setReadyState(Document::Interactive);
@@ -140,4 +175,36 @@
 {
 }
 
+void NewXMLDocumentParser::notifyFinished(CachedResource* unusedResource)
+{
+    ASSERT_UNUSED(unusedResource, unusedResource == m_pendingScript);
+    ASSERT(m_pendingScript->accessCount() > 0);
+
+    ScriptSourceCode sourceCode(m_pendingScript.get());
+    bool errorOccurred = m_pendingScript->errorOccurred();
+    bool wasCanceled = m_pendingScript->wasCanceled();
+
+    m_pendingScript->removeClient(this);
+    m_pendingScript = 0;
+
+    RefPtr<Element> element = m_scriptElement;
+    ScriptElement* scriptElement = toScriptElement(m_scriptElement.get());
+    m_scriptElement = 0;
+
+    ASSERT(scriptElement);
+
+    // _javascript_ can detach this parser, make sure it's kept alive even if detached.
+    RefPtr<NewXMLDocumentParser> protect(this);
+
+    if (errorOccurred)
+        scriptElement->dispatchErrorEvent();
+    else if (!wasCanceled) {
+        scriptElement->executeScript(sourceCode);
+        scriptElement->dispatchLoadEvent();
+    }
+
+    if (!isDetached() && m_parserPaused)
+        resumeParsing();
 }
+
+}

Modified: trunk/Source/WebCore/xml/parser/NewXMLDocumentParser.h (93379 => 93380)


--- trunk/Source/WebCore/xml/parser/NewXMLDocumentParser.h	2011-08-19 01:04:12 UTC (rev 93379)
+++ trunk/Source/WebCore/xml/parser/NewXMLDocumentParser.h	2011-08-19 01:09:34 UTC (rev 93380)
@@ -27,6 +27,8 @@
 #define NewXMLDocumentParser_h
 
 #include "CachedResourceClient.h"
+#include "CachedResourceHandle.h"
+#include "CachedScript.h"
 #include "ScriptableDocumentParser.h"
 #include "XMLToken.h"
 #include "XMLTokenizer.h"
@@ -35,11 +37,12 @@
 
 namespace WebCore {
 
+class ContainerNode;
 class Document;
-class ContainerNode;
+class ScriptElement;
 class XMLTreeBuilder;
 
-class NewXMLDocumentParser : public ScriptableDocumentParser {
+class NewXMLDocumentParser : public ScriptableDocumentParser, public CachedResourceClient {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     static PassRefPtr<NewXMLDocumentParser> create(Document* document)
@@ -54,6 +57,10 @@
 
     static bool parseDocumentFragment(const String&, DocumentFragment*, Element* parent = 0, FragmentScriptingPermission = FragmentScriptingAllowed);
 
+    void pauseParsing() { m_parserPaused = true; }
+    void resumeParsing();
+    void processScript(ScriptElement*);
+
     virtual TextPosition0 textPosition() const;
     virtual int lineNumber() const;
 
@@ -64,6 +71,9 @@
     virtual bool isExecutingScript() const;
     virtual void executeScriptsWaitingForStylesheets();
 
+    // CachedResourceClient
+    virtual void notifyFinished(CachedResource*);
+
 protected:
     virtual void insert(const SegmentedString&);
     virtual void append(const SegmentedString&);
@@ -74,11 +84,16 @@
     NewXMLDocumentParser(DocumentFragment*, Element* parent, FragmentScriptingPermission);
     virtual ~NewXMLDocumentParser();
 
+    SegmentedString m_input;
     OwnPtr<XMLTokenizer> m_tokenizer;
     XMLToken m_token;
 
+    bool m_parserPaused;
     bool m_finishWasCalled;
 
+    CachedResourceHandle<CachedScript> m_pendingScript;
+    RefPtr<Element> m_scriptElement;
+
     OwnPtr<XMLTreeBuilder> m_treeBuilder;
 };
 

Modified: trunk/Source/WebCore/xml/parser/XMLTreeBuilder.cpp (93379 => 93380)


--- trunk/Source/WebCore/xml/parser/XMLTreeBuilder.cpp	2011-08-19 01:04:12 UTC (rev 93379)
+++ trunk/Source/WebCore/xml/parser/XMLTreeBuilder.cpp	2011-08-19 01:09:34 UTC (rev 93380)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "XMLTreeBuilder.h"
 
+#include "CachedScript.h"
 #include "CDATASection.h"
 #include "Comment.h"
 #include "Document.h"
@@ -35,6 +36,8 @@
 #include "HTMLEntitySearch.h"
 #include "NewXMLDocumentParser.h"
 #include "ProcessingInstruction.h"
+#include "ScriptElement.h"
+#include "ScriptSourceCode.h"
 #include "XMLNSNames.h"
 #include "XMLNames.h"
 
@@ -143,6 +146,17 @@
     m_currentNodeStack.removeLast();
 }
 
+void XMLTreeBuilder::closeElement(PassRefPtr<Element> element)
+{
+    element->finishParsingChildren();
+
+    ScriptElement* scriptElement = toScriptElement(element.get());
+    if (scriptElement)
+        m_parser->processScript(scriptElement);
+
+    popCurrentNode();
+}
+
 void XMLTreeBuilder::processProcessingInstruction(const AtomicXMLToken& token)
 {
     if (!failOnText())
@@ -230,10 +244,8 @@
     if (isFirstElement && m_document->frame())
         m_document->frame()->loader()->dispatchDocumentElementAvailable();
 
-    if (token.selfClosing()) {
-        popCurrentNode();
-        newElement->finishParsingChildren();
-    }
+    if (token.selfClosing())
+        closeElement(newElement);
 }
 
 void XMLTreeBuilder::processEndTag(const AtomicXMLToken& token)
@@ -245,8 +257,7 @@
     if (!node->hasTagName(QualifiedName(token.prefix(), token.name(), m_currentNodeStack.last().namespaceForPrefix(token.prefix(), m_currentNodeStack.last().namespaceURI()))))
         m_parser->stopParsing();
 
-    popCurrentNode();
-    node->finishParsingChildren();
+    closeElement(toElement(node.get()));
 }
 
 void XMLTreeBuilder::processCharacter(const AtomicXMLToken& token)

Modified: trunk/Source/WebCore/xml/parser/XMLTreeBuilder.h (93379 => 93380)


--- trunk/Source/WebCore/xml/parser/XMLTreeBuilder.h	2011-08-19 01:04:12 UTC (rev 93379)
+++ trunk/Source/WebCore/xml/parser/XMLTreeBuilder.h	2011-08-19 01:09:34 UTC (rev 93380)
@@ -81,6 +81,7 @@
 
     void pushCurrentNode(const NodeStackItem&);
     void popCurrentNode();
+    void closeElement(PassRefPtr<Element>);
 
     void processProcessingInstruction(const AtomicXMLToken&);
     void processXMLDeclaration(const AtomicXMLToken&);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to