Changeset 61966 in webkit


Ignore:
Timestamp:
Jun 27, 2010 1:38:22 AM (14 years ago)
Author:
abarth@webkit.org
Message:

2010-06-27 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

HTML5 tree builder should be able to execute inline scripts
https://bugs.webkit.org/show_bug.cgi?id=41257

This patch implements enough machinery so that we can execute inline
scripts in extremely simple documents such as the following:

<html>
<script>
alert(1);
</script>

To get this to work, I had to flesh out a surprising amount of the data
structures for processing the <head>. No tests because this is
already covered by most LayoutTests.

  • html/HTMLTreeBuilder.cpp: (WebCore::HTMLTreeBuilder::HTMLTreeBuilder): (WebCore::HTMLTreeBuilder::constructTreeFromToken): (WebCore::HTMLTreeBuilder::processStartTag): (WebCore::HTMLTreeBuilder::processEndTag): (WebCore::HTMLTreeBuilder::processCharacter): (WebCore::HTMLTreeBuilder::insertComment): (WebCore::HTMLTreeBuilder::insertElement): (WebCore::HTMLTreeBuilder::insertScriptElement):
  • html/HTMLTreeBuilder.h: (WebCore::HTMLTreeBuilder::ElementRecord::ElementRecord): (WebCore::HTMLTreeBuilder::ElementRecord::element): (WebCore::HTMLTreeBuilder::ElementRecord::next): (WebCore::HTMLTreeBuilder::ElementRecord::releaseNext): (WebCore::HTMLTreeBuilder::ElementRecord::setNext): (WebCore::HTMLTreeBuilder::ElementStack::pop): (WebCore::HTMLTreeBuilder::ElementStack::push): (WebCore::HTMLTreeBuilder::ElementStack::top): (WebCore::HTMLTreeBuilder::ElementStack::remove): (WebCore::HTMLTreeBuilder::currentElement):
Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r61964 r61966  
     12010-06-27  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        HTML5 tree builder should be able to execute inline scripts
     6        https://bugs.webkit.org/show_bug.cgi?id=41257
     7
     8        This patch implements enough machinery so that we can execute inline
     9        scripts in extremely simple documents such as the following:
     10
     11        <html>
     12        <script>
     13        alert(1);
     14        </script>
     15
     16        To get this to work, I had to flesh out a surprising amount of the data
     17        structures for processing the <head>.  No tests because this is
     18        already covered by most LayoutTests.
     19
     20        * html/HTMLTreeBuilder.cpp:
     21        (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
     22        (WebCore::HTMLTreeBuilder::constructTreeFromToken):
     23        (WebCore::HTMLTreeBuilder::processStartTag):
     24        (WebCore::HTMLTreeBuilder::processEndTag):
     25        (WebCore::HTMLTreeBuilder::processCharacter):
     26        (WebCore::HTMLTreeBuilder::insertComment):
     27        (WebCore::HTMLTreeBuilder::insertElement):
     28        (WebCore::HTMLTreeBuilder::insertScriptElement):
     29        * html/HTMLTreeBuilder.h:
     30        (WebCore::HTMLTreeBuilder::ElementRecord::ElementRecord):
     31        (WebCore::HTMLTreeBuilder::ElementRecord::element):
     32        (WebCore::HTMLTreeBuilder::ElementRecord::next):
     33        (WebCore::HTMLTreeBuilder::ElementRecord::releaseNext):
     34        (WebCore::HTMLTreeBuilder::ElementRecord::setNext):
     35        (WebCore::HTMLTreeBuilder::ElementStack::pop):
     36        (WebCore::HTMLTreeBuilder::ElementStack::push):
     37        (WebCore::HTMLTreeBuilder::ElementStack::top):
     38        (WebCore::HTMLTreeBuilder::ElementStack::remove):
     39        (WebCore::HTMLTreeBuilder::currentElement):
     40
    1412010-06-26  Brady Eidson  <beidson@apple.com>
    242
  • trunk/WebCore/html/HTMLTreeBuilder.cpp

    r61925 r61966  
    2727#include "HTMLTreeBuilder.h"
    2828
     29#include "Comment.h"
    2930#include "DocumentFragment.h"
    3031#include "Element.h"
    3132#include "Frame.h"
     33#include "HTMLElementFactory.h"
     34#include "HTMLScriptElement.h"
    3235#include "HTMLTokenizer.h"
    3336#include "HTMLToken.h"
     
    3942#include "NotImplemented.h"
    4043#include "ScriptController.h"
     44#include "Text.h"
    4145#include <wtf/UnusedParam.h>
    4246
     
    6266    , m_isPaused(false)
    6367    , m_insertionMode(InitialMode)
     68    , m_originalInsertionMode(InitialMode)
    6469    , m_tokenizer(tokenizer)
    6570    , m_legacyTreeBuilder(new LegacyHTMLTreeBuilder(document, reportErrors))
     
    7883    , m_isPaused(false)
    7984    , m_insertionMode(InitialMode)
     85    , m_originalInsertionMode(InitialMode)
    8086    , m_tokenizer(tokenizer)
    8187    , m_legacyTreeBuilder(new LegacyHTMLTreeBuilder(fragment, scriptingPermission))
     
    302308        }
    303309        if (token.name() == headTag) {
    304             m_headElement = insertElement(token);
     310            insertElement(token);
     311            m_headElement = currentElement();
    305312            setInsertionMode(InHeadMode);
    306313            return;
     
    461468        ASSERT(insertionMode() == InHeadNoscriptMode);
    462469        if (token.name() == noscriptTag) {
    463             ASSERT(m_openElements.top()->tagQName() == noscriptTag);
     470            ASSERT(currentElement()->tagQName() == noscriptTag);
    464471            m_openElements.pop();
    465             ASSERT(m_openElements.top()->tagQName() == headTag);
     472            ASSERT(currentElement()->tagQName() == headTag);
    466473            setInsertionMode(InHeadMode);
    467474            return;
     
    473480        processDefaultForInHeadNoscriptMode(token);
    474481        processToken(token);
     482    case TextMode:
     483        if (token.name() == scriptTag) {
     484            // Pause ourselves so that parsing stops until the script can be processed by the caller.
     485            m_isPaused = true;
     486            ASSERT(currentElement()->tagQName() == scriptTag);
     487            m_scriptToProcess = currentElement();
     488            m_openElements.pop();
     489            m_insertionMode = m_originalInsertionMode;
     490            return;
     491        }
     492        notImplemented();
     493        break;
    475494    default:
    476495        notImplemented();
     
    487506}
    488507
    489 void HTMLTreeBuilder::processCharacter(AtomicHTMLToken&)
    490 {
     508void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
     509{
     510    if (insertionMode() == TextMode) {
     511        currentElement()->addChild(Text::create(m_document, token.characters()));
     512        return;
     513    }
    491514    // FIXME: We need to figure out how to handle each character individually.
    492515    notImplemented();
     
    575598void HTMLTreeBuilder::insertComment(AtomicHTMLToken& token)
    576599{
    577     ASSERT_UNUSED(token, token.type() == HTMLToken::Comment);
    578 }
    579 
    580 PassRefPtr<Element> HTMLTreeBuilder::insertElement(AtomicHTMLToken& token)
     600    ASSERT(token.type() == HTMLToken::Comment);
     601    RefPtr<Node> element = Comment::create(m_document, token.comment());
     602    currentElement()->addChild(element);
     603}
     604
     605void HTMLTreeBuilder::insertElement(AtomicHTMLToken& token)
     606{
     607    ASSERT(token.type() == HTMLToken::StartTag);
     608    RefPtr<Element> element = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, token.name(), xhtmlNamespaceURI), m_document, 0);
     609    currentElement()->addChild(element);
     610    m_openElements.push(element.release());
     611}
     612
     613void HTMLTreeBuilder::insertCharacter(UChar cc)
     614{
     615    ASSERT_UNUSED(cc, cc);
     616}
     617
     618void HTMLTreeBuilder::insertGenericRCDATAElement(AtomicHTMLToken& token)
    581619{
    582620    ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
    583     return 0;
    584 }
    585 
    586 void HTMLTreeBuilder::insertCharacter(UChar cc)
    587 {
    588     ASSERT_UNUSED(cc, cc);
    589 }
    590 
    591 void HTMLTreeBuilder::insertGenericRCDATAElement(AtomicHTMLToken& token)
     621}
     622
     623void HTMLTreeBuilder::insertGenericRawTextElement(AtomicHTMLToken& token)
    592624{
    593625    ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
    594626}
    595627
    596 void HTMLTreeBuilder::insertGenericRawTextElement(AtomicHTMLToken& token)
     628void HTMLTreeBuilder::insertScriptElement(AtomicHTMLToken& token)
    597629{
    598630    ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
    599 }
    600 
    601 void HTMLTreeBuilder::insertScriptElement(AtomicHTMLToken& token)
    602 {
    603     ASSERT_UNUSED(token, token.type() == HTMLToken::StartTag);
     631    RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, m_document, true);
     632    currentElement()->addChild(element);
     633    m_openElements.push(element.release());
     634    m_tokenizer->setState(HTMLTokenizer::ScriptDataState);
     635    m_originalInsertionMode = m_insertionMode;
     636    m_insertionMode = TextMode;
    604637}
    605638
  • trunk/WebCore/html/HTMLTreeBuilder.h

    r61925 r61966  
    3131#include <wtf/Noncopyable.h>
    3232#include <wtf/OwnPtr.h>
     33#include <wtf/PassOwnPtr.h>
    3334#include <wtf/PassRefPtr.h>
    3435#include <wtf/RefPtr.h>
     
    100101    };
    101102
     103    class ElementRecord : public Noncopyable {
     104    public:
     105        ElementRecord(PassRefPtr<Element> element, PassOwnPtr<ElementRecord> next)
     106            : m_element(element)
     107            , m_next(next)
     108        {
     109        }
     110
     111        Element* element() const { return m_element.get(); }
     112        ElementRecord* next() const { return m_next.get(); }
     113        PassOwnPtr<ElementRecord> releaseNext() { return m_next.release(); }
     114        void setNext(PassOwnPtr<ElementRecord> next) { m_next = next; }
     115
     116    private:
     117        RefPtr<Element> m_element;
     118        OwnPtr<ElementRecord> m_next;
     119    };
     120
    102121    class ElementStack : public Noncopyable {
    103122    public:
    104         void pop() { }
    105         void push(PassRefPtr<Element>) { }
    106         void remove(Element*) { }
    107         Element* top() const { return 0; }
     123        void pop()
     124        {
     125            m_top = m_top->releaseNext();
     126        }
     127
     128        void push(PassRefPtr<Element> element)
     129        {
     130            m_top.set(new ElementRecord(element, m_top.release()));
     131        }
     132
     133        Element* top() const
     134        {
     135            return m_top->element();
     136        }
     137
     138        void remove(Element* element)
     139        {
     140            if (m_top->element() == element) {
     141                pop();
     142                return;
     143            }
     144            ElementRecord* pos = m_top.get();
     145            while (pos->next()) {
     146                if (pos->next()->element() == element) {
     147                    pos->setNext(pos->next()->releaseNext());
     148                    return;
     149                }
     150            }
     151        }
     152
     153    private:
     154        OwnPtr<ElementRecord> m_top;
    108155    };
    109156
     
    129176    void insertDoctype(AtomicHTMLToken&);
    130177    void insertComment(AtomicHTMLToken&);
    131     PassRefPtr<Element> insertElement(AtomicHTMLToken&);
     178    void insertElement(AtomicHTMLToken&);
    132179    void insertCharacter(UChar cc);
    133180    void insertGenericRCDATAElement(AtomicHTMLToken&);
     
    138185    void insertHTMLStartTagInBody(AtomicHTMLToken&);
    139186
     187    Element* currentElement() { return m_openElements.top(); }
     188
    140189    RefPtr<Element> m_headElement;
    141190    ElementStack m_openElements;
     
    158207
    159208    InsertionMode m_insertionMode;
     209    InsertionMode m_originalInsertionMode;
    160210
    161211    // HTML5 spec requires that we be able to change the state of the tokenizer
Note: See TracChangeset for help on using the changeset viewer.