Changeset 62166 in webkit


Ignore:
Timestamp:
Jun 30, 2010 1:18:54 AM (14 years ago)
Author:
eric@webkit.org
Message:

2010-06-28 Eric Seidel <eric@webkit.org>

Reviewed by Adam Barth.

Teach HTML5TreeBuilder how to merge attributes from extra html/body elements
https://bugs.webkit.org/show_bug.cgi?id=41337

  • html5lib/resources/webkit01.dat: Add a test for double body.

2010-06-28 Eric Seidel <eric@webkit.org>

Reviewed by Adam Barth.

Teach HTML5TreeBuilder how to merge attributes from extra html/body elements
https://bugs.webkit.org/show_bug.cgi?id=41337

Had to teach ElementStack to store pointers to html, head, and body
elements.

This fixed a few tests in LayoutTests/html5lib.

  • html/HTMLTreeBuilder.cpp: (WebCore::HTMLTreeBuilder::insertHTMLStartTagBeforeHTML): (WebCore::HTMLTreeBuilder::mergeAttributesFromTokenIntoElement): (WebCore::HTMLTreeBuilder::insertHTMLStartTagInBody): (WebCore::HTMLTreeBuilder::processStartTag): (WebCore::HTMLTreeBuilder::processEndTag): (WebCore::HTMLTreeBuilder::createElementAndAttachToCurrent): (WebCore::HTMLTreeBuilder::insertHTMLHtmlElement): (WebCore::HTMLTreeBuilder::insertHTMLHeadElement): (WebCore::HTMLTreeBuilder::insertHTMLBodyElement): (WebCore::HTMLTreeBuilder::insertElement): (WebCore::HTMLTreeBuilder::insertGenericRCDATAElement): (WebCore::HTMLTreeBuilder::insertGenericRawTextElement):
  • html/HTMLTreeBuilder.h: (WebCore::HTMLTreeBuilder::ElementStack::ElementStack): (WebCore::HTMLTreeBuilder::ElementStack::popHTMLHeadElement): (WebCore::HTMLTreeBuilder::ElementStack::pop): (WebCore::HTMLTreeBuilder::ElementStack::pushHTMLHtmlElement): (WebCore::HTMLTreeBuilder::ElementStack::pushHTMLHeadElement): (WebCore::HTMLTreeBuilder::ElementStack::pushHTMLBodyElement): (WebCore::HTMLTreeBuilder::ElementStack::push): (WebCore::HTMLTreeBuilder::ElementStack::removeHTMLHeadElement): (WebCore::HTMLTreeBuilder::ElementStack::remove): (WebCore::HTMLTreeBuilder::ElementStack::htmlElement): (WebCore::HTMLTreeBuilder::ElementStack::headElement): (WebCore::HTMLTreeBuilder::ElementStack::bodyElement): (WebCore::HTMLTreeBuilder::ElementStack::pushCommon): (WebCore::HTMLTreeBuilder::ElementStack::popCommon): (WebCore::HTMLTreeBuilder::ElementStack::removeNonFirstCommon):
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r62165 r62166  
     12010-06-28  Eric Seidel  <eric@webkit.org>
     2
     3        Reviewed by Adam Barth.
     4
     5        Teach HTML5TreeBuilder how to merge attributes from extra html/body elements
     6        https://bugs.webkit.org/show_bug.cgi?id=41337
     7
     8        * html5lib/resources/webkit01.dat: Add a test for double body.
     9
    1102010-06-30  Yury Semikhatsky  <yurys@chromium.org>
    211
  • trunk/LayoutTests/html5lib/resources/webkit01.dat

    r61239 r62166  
    219219|   <body>
    220220|     "<"
     221
     222#data
     223<body foo='bar'><body foo='baz' yo='mama'>
     224#errors
     225#document
     226| <html>
     227|   <head>
     228|   <body>
     229|     foo="bar"
     230|     yo="mama"
  • trunk/LayoutTests/html5lib/runner-expected-html5.txt

    r62091 r62166  
    787811
    797913
    80 14
    818017
    828118
     
    10410348
    10510449
    106 50
    10710551
    108 52
    10910653
    11010754
     
    2762732
    277274
    278 resources/tests14.dat:
    279 3
    280 6
     275resources/tests14.dat: PASS
    281276
    282277resources/tests15.dat:
  • trunk/WebCore/ChangeLog

    r62164 r62166  
     12010-06-28  Eric Seidel  <eric@webkit.org>
     2
     3        Reviewed by Adam Barth.
     4
     5        Teach HTML5TreeBuilder how to merge attributes from extra html/body elements
     6        https://bugs.webkit.org/show_bug.cgi?id=41337
     7
     8        Had to teach ElementStack to store pointers to html, head, and body
     9        elements.
     10
     11        This fixed a few tests in LayoutTests/html5lib.
     12
     13        * html/HTMLTreeBuilder.cpp:
     14        (WebCore::HTMLTreeBuilder::insertHTMLStartTagBeforeHTML):
     15        (WebCore::HTMLTreeBuilder::mergeAttributesFromTokenIntoElement):
     16        (WebCore::HTMLTreeBuilder::insertHTMLStartTagInBody):
     17        (WebCore::HTMLTreeBuilder::processStartTag):
     18        (WebCore::HTMLTreeBuilder::processEndTag):
     19        (WebCore::HTMLTreeBuilder::createElementAndAttachToCurrent):
     20        (WebCore::HTMLTreeBuilder::insertHTMLHtmlElement):
     21        (WebCore::HTMLTreeBuilder::insertHTMLHeadElement):
     22        (WebCore::HTMLTreeBuilder::insertHTMLBodyElement):
     23        (WebCore::HTMLTreeBuilder::insertElement):
     24        (WebCore::HTMLTreeBuilder::insertGenericRCDATAElement):
     25        (WebCore::HTMLTreeBuilder::insertGenericRawTextElement):
     26        * html/HTMLTreeBuilder.h:
     27        (WebCore::HTMLTreeBuilder::ElementStack::ElementStack):
     28        (WebCore::HTMLTreeBuilder::ElementStack::popHTMLHeadElement):
     29        (WebCore::HTMLTreeBuilder::ElementStack::pop):
     30        (WebCore::HTMLTreeBuilder::ElementStack::pushHTMLHtmlElement):
     31        (WebCore::HTMLTreeBuilder::ElementStack::pushHTMLHeadElement):
     32        (WebCore::HTMLTreeBuilder::ElementStack::pushHTMLBodyElement):
     33        (WebCore::HTMLTreeBuilder::ElementStack::push):
     34        (WebCore::HTMLTreeBuilder::ElementStack::removeHTMLHeadElement):
     35        (WebCore::HTMLTreeBuilder::ElementStack::remove):
     36        (WebCore::HTMLTreeBuilder::ElementStack::htmlElement):
     37        (WebCore::HTMLTreeBuilder::ElementStack::headElement):
     38        (WebCore::HTMLTreeBuilder::ElementStack::bodyElement):
     39        (WebCore::HTMLTreeBuilder::ElementStack::pushCommon):
     40        (WebCore::HTMLTreeBuilder::ElementStack::popCommon):
     41        (WebCore::HTMLTreeBuilder::ElementStack::removeNonFirstCommon):
     42
    1432010-06-30  José Millán Soto  <jmillan@igalia.com>
    244
  • trunk/WebCore/html/HTMLTreeBuilder.cpp

    r62090 r62166  
    284284    RefPtr<Element> element = HTMLHtmlElement::create(m_document);
    285285    element->setAttributeMap(token.attributes(), m_fragmentScriptingPermission);
    286     m_openElements.push(attach(m_document, element.release()));
    287 }
    288 
    289 void HTMLTreeBuilder::insertHTMLStartTagInBody(AtomicHTMLToken&)
    290 {
    291     notImplemented();
     286    m_openElements.pushHTMLHtmlElement(attach(m_document, element.release()));
     287}
     288
     289void HTMLTreeBuilder::mergeAttributesFromTokenIntoElement(AtomicHTMLToken& token, Element* element)
     290{
     291    if (!token.attributes())
     292        return;
     293
     294    NamedNodeMap* attributes = element->attributes(false);
     295    for (unsigned i = 0; i < token.attributes()->length(); ++i) {
     296        Attribute* attribute = token.attributes()->attributeItem(i);
     297        if (!attributes->getAttributeItem(attribute->name()))
     298            element->setAttribute(attribute->name(), attribute->value());
     299    }
     300}
     301
     302void HTMLTreeBuilder::insertHTMLStartTagInBody(AtomicHTMLToken& token)
     303{
     304    parseError(token);
     305    mergeAttributesFromTokenIntoElement(token, m_openElements.htmlElement());
    292306}
    293307
     
    315329        }
    316330        if (token.name() == headTag) {
    317             insertElement(token);
    318             m_headElement = currentElement();
     331            insertHTMLHeadElement(token);
    319332            setInsertionMode(InHeadMode);
    320333            return;
     
    336349        if (token.name() == bodyTag) {
    337350            m_framesetOk = false;
    338             insertElement(token);
     351            insertHTMLBodyElement(token);
    339352            m_insertionMode = InBodyMode;
    340353            return;
     
    348361            parseError(token);
    349362            ASSERT(m_headElement);
    350             m_openElements.push(m_headElement);
    351             notImplemented();
    352             m_openElements.remove(m_headElement.get());
     363            m_openElements.pushHTMLHeadElement(m_headElement);
     364            notImplemented();
     365            m_openElements.removeHTMLHeadElement(m_headElement.get());
    353366            return;
    354367        }
     
    372385        if (token.name() == bodyTag) {
    373386            parseError(token);
    374             notImplemented();
     387            notImplemented(); // fragment case
     388            mergeAttributesFromTokenIntoElement(token, m_openElements.bodyElement());
    375389            return;
    376390        }
     
    597611        ASSERT(insertionMode() == InHeadMode);
    598612        if (token.name() == headTag) {
    599             ASSERT(m_openElements.top()->tagQName() == headTag);
    600             m_openElements.pop();
     613            m_openElements.popHTMLHeadElement();
    601614            setInsertionMode(AfterHeadMode);
    602615            return;
     
    937950}
    938951
     952PassRefPtr<Element> HTMLTreeBuilder::createElementAndAttachToCurrent(AtomicHTMLToken& token)
     953{
     954    ASSERT(token.type() == HTMLToken::StartTag);
     955    return attach(currentElement(), createElement(token));
     956}
     957
     958void HTMLTreeBuilder::insertHTMLHtmlElement(AtomicHTMLToken& token)
     959{
     960    m_openElements.pushHTMLHtmlElement(createElementAndAttachToCurrent(token));
     961}
     962
     963void HTMLTreeBuilder::insertHTMLHeadElement(AtomicHTMLToken& token)
     964{
     965    m_headElement = createElementAndAttachToCurrent(token);
     966    m_openElements.pushHTMLHeadElement(m_headElement);
     967}
     968
     969void HTMLTreeBuilder::insertHTMLBodyElement(AtomicHTMLToken& token)
     970{
     971    m_openElements.pushHTMLBodyElement(createElementAndAttachToCurrent(token));
     972}
     973
    939974void HTMLTreeBuilder::insertElement(AtomicHTMLToken& token)
    940975{
    941     ASSERT(token.type() == HTMLToken::StartTag);
    942     m_openElements.push(attach(currentElement(), createElement(token)));
     976    m_openElements.push(createElementAndAttachToCurrent(token));
    943977}
    944978
     
    962996void HTMLTreeBuilder::insertGenericRCDATAElement(AtomicHTMLToken& token)
    963997{
    964     ASSERT(token.type() == HTMLToken::StartTag);
    965998    insertElement(token);
    966999    m_tokenizer->setState(HTMLTokenizer::RCDATAState);
     
    9711004void HTMLTreeBuilder::insertGenericRawTextElement(AtomicHTMLToken& token)
    9721005{
    973     ASSERT(token.type() == HTMLToken::StartTag);
    9741006    insertElement(token);
    9751007    m_tokenizer->setState(HTMLTokenizer::RAWTEXTState);
  • trunk/WebCore/html/HTMLTreeBuilder.h

    r62090 r62166  
    2929#include "Element.h"
    3030#include "FragmentScriptingPermission.h"
     31#include "HTMLNames.h"
    3132#include "HTMLTokenizer.h"
    3233#include <wtf/Noncopyable.h>
     
    121122    class ElementStack : public Noncopyable {
    122123    public:
     124        ElementStack()
     125            : m_htmlElement(0)
     126            , m_headElement(0)
     127            , m_bodyElement(0)
     128        {
     129        }
     130
     131        void popHTMLHeadElement()
     132        {
     133            ASSERT(top() == m_headElement);
     134            m_headElement = 0;
     135            popCommon();
     136        }
     137
    123138        void pop()
    124139        {
    125             top()->finishParsingChildren();
    126             m_top = m_top->releaseNext();
     140            ASSERT(!top()->hasTagName(HTMLNames::headTag));
     141            popCommon();
     142        }
     143
     144        void pushHTMLHtmlElement(PassRefPtr<Element> element)
     145        {
     146            ASSERT(element->hasTagName(HTMLNames::htmlTag));
     147            ASSERT(!m_htmlElement);
     148            m_htmlElement = element.get();
     149            pushCommon(element);
     150        }
     151
     152        void pushHTMLHeadElement(PassRefPtr<Element> element)
     153        {
     154            ASSERT(element->hasTagName(HTMLNames::headTag));
     155            ASSERT(!m_headElement);
     156            m_headElement = element.get();
     157            pushCommon(element);
     158        }
     159
     160        void pushHTMLBodyElement(PassRefPtr<Element> element)
     161        {
     162            ASSERT(element->hasTagName(HTMLNames::bodyTag));
     163            ASSERT(!m_bodyElement);
     164            m_bodyElement = element.get();
     165            pushCommon(element);
    127166        }
    128167
    129168        void push(PassRefPtr<Element> element)
    130169        {
    131             m_top.set(new ElementRecord(element, m_top.release()));
    132             top()->beginParsingChildren();
     170            ASSERT(!element->hasTagName(HTMLNames::htmlTag));
     171            ASSERT(!element->hasTagName(HTMLNames::headTag));
     172            ASSERT(!element->hasTagName(HTMLNames::bodyTag));
     173            ASSERT(m_htmlElement);
     174            pushCommon(element);
    133175        }
    134176
     
    138180        }
    139181
     182        void removeHTMLHeadElement(Element* element)
     183        {
     184            ASSERT(m_headElement == element);
     185            if (m_top->element() == element) {
     186                popHTMLHeadElement();
     187                return;
     188            }
     189            m_headElement = 0;
     190            removeNonFirstCommon(element);
     191        }
     192
    140193        void remove(Element* element)
    141194        {
     195            ASSERT(!element->hasTagName(HTMLNames::headTag));
    142196            if (m_top->element() == element) {
    143197                pop();
    144198                return;
    145199            }
    146             ElementRecord* pos = m_top.get();
    147             while (pos->next()) {
    148                 if (pos->next()->element() == element) {
    149                     pos->setNext(pos->next()->releaseNext());
    150                     return;
    151                 }
    152             }
     200            removeNonFirstCommon(element);
    153201        }
    154202
     
    178226        }
    179227
     228        Element* htmlElement()
     229        {
     230            ASSERT(m_htmlElement);
     231            return m_htmlElement;
     232        }
     233
     234        Element* headElement()
     235        {
     236            ASSERT(m_headElement);
     237            return m_headElement;
     238        }
     239
     240        Element* bodyElement()
     241        {
     242            ASSERT(m_bodyElement);
     243            return m_bodyElement;
     244        }
     245
    180246    private:
     247        void pushCommon(PassRefPtr<Element> element)
     248        {
     249            m_top.set(new ElementRecord(element, m_top.release()));
     250            top()->beginParsingChildren();
     251        }
     252
     253        void popCommon()
     254        {
     255            ASSERT(!top()->hasTagName(HTMLNames::htmlTag));
     256            ASSERT(!top()->hasTagName(HTMLNames::bodyTag));
     257            top()->finishParsingChildren();
     258            m_top = m_top->releaseNext();
     259        }
     260
     261        void removeNonFirstCommon(Element* element)
     262        {
     263            ASSERT(!element->hasTagName(HTMLNames::htmlTag));
     264            ASSERT(!element->hasTagName(HTMLNames::bodyTag));
     265            ElementRecord* pos = m_top.get();
     266            ASSERT(pos->element() != element);
     267            while (pos->next()) {
     268                if (pos->next()->element() == element) {
     269                    // FIXME: Is it OK to call finishParsingChildren()
     270                    // when the children aren't actually finished?
     271                    element->finishParsingChildren();
     272                    pos->setNext(pos->next()->releaseNext());
     273                    return;
     274                }
     275            }
     276            ASSERT_NOT_REACHED();
     277        }
     278
    181279        OwnPtr<ElementRecord> m_top;
     280
     281        // We remember <html>, <head> and <body> as they are pushed.  Their
     282        // ElementRecords keep them alive.  <html> and <body> are never popped.
     283        // FIXME: We don't currently require type-specific information about
     284        // these elements so we haven't yet bothered to plumb the types all the
     285        // way down through createElement, etc.
     286        Element* m_htmlElement;
     287        Element* m_headElement;
     288        Element* m_bodyElement;
    182289    };
    183290
     
    220327    void insertComment(AtomicHTMLToken&);
    221328    void insertCommentOnDocument(AtomicHTMLToken&);
     329    void insertHTMLHtmlElement(AtomicHTMLToken&);
     330    void insertHTMLHeadElement(AtomicHTMLToken&);
     331    void insertHTMLBodyElement(AtomicHTMLToken&);
    222332    void insertElement(AtomicHTMLToken&);
    223333    void insertSelfClosingElement(AtomicHTMLToken&);
     
    232342
    233343    PassRefPtr<Element> createElement(AtomicHTMLToken&);
     344    PassRefPtr<Element> createElementAndAttachToCurrent(AtomicHTMLToken&);
     345
     346    void mergeAttributesFromTokenIntoElement(AtomicHTMLToken&, Element*);
    234347
    235348    bool indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const;
Note: See TracChangeset for help on using the changeset viewer.