Changeset 20170 in webkit


Ignore:
Timestamp:
Mar 13, 2007 4:18:23 PM (17 years ago)
Author:
darin
Message:

LayoutTests:

Reviewed by Maciej.

  • fast/canvas/canvas-hides-fallback-expected.txt: Added.
  • fast/canvas/canvas-hides-fallback.html: Added.
  • fast/canvas/script-inside-canvas-fallback-expected.txt: Added.
  • fast/canvas/script-inside-canvas-fallback.html: Added.
  • fast/canvas/unclosed-canvas-1-expected.txt: Added.
  • fast/canvas/unclosed-canvas-1.html: Added.
  • fast/canvas/unclosed-canvas-2-expected.txt: Added.
  • fast/canvas/unclosed-canvas-2.html: Added.
  • fast/canvas/unclosed-canvas-3-expected.txt: Added.
  • fast/canvas/unclosed-canvas-3.html: Added.
  • fast/canvas/unclosed-canvas-4-expected.txt: Added.
  • fast/canvas/unclosed-canvas-4.html: Added.

WebCore:

Reviewed by Maciej.

Change <canvas> elements so that their contents are parsed normally,
but not rendered. This change fixes the bug, because normal parsing
rules close the <canvas> element in that case. The special parser
stuff was just getting in the way.

Also do some basic cleanup to the HTML parser. This was motivated by
an earlier version of this patch that made even more changes to the
parser, but the cleanup is still worth landing.

Test: fast/canvas/canvas-hides-fallback.html
Test: fast/canvas/script-inside-canvas-fallback.html
Test: fast/canvas/unclosed-canvas-1.html
Test: fast/canvas/unclosed-canvas-2.html
Test: fast/canvas/unclosed-canvas-3.html
Test: fast/canvas/unclosed-canvas-4.html

  • html/HTMLCanvasElement.h: Added a data member to keep track of whether the renderer is a RenderHTMLCanvas or not.
  • html/HTMLCanvasElement.cpp: (WebCore::HTMLCanvasElement::createRenderer): If JavaScript is enabled, create a RenderHTMLCanvas. If it's not, let the default code create the default type of renderer, which will result in fallback content being visible. The RenderHTMLCanvas class already hides all of its children. Set the m_rendererIsCanvas boolean accordingly. Since the actual storage for the canvas is allocated lazily when you actually get a drawing context, we don't need to do anything special to prevent it when JavaScript is disabled; the relevant functions won't be called. (WebCore::HTMLCanvasElement::reset): Protect the code that manipulates the RenderHTMLCanvas with a check of m_rendererIsCanvas. This is the only code inside the DOM element that relies on the renderer type.
  • html/HTMLParser.h: Removed unneeded includes. Marked HTMLParser as Noncopyable. Changed the Document parameter to the constructor to instead of HTMLDocument. Renamed discard_until to m_skipModeTag for clarity. Removed unused noSpaces function and unneeded public doc() function. Moved data members all down to the end so you can see them together in order. Renamed map to m_currentMapElement and isindex to m_isindexElement. Removed unused end and headLoaded data members. Renamed m_fragment to m_isParsingFragment to make it clearer that it's a boolean, not a fragment.
  • html/HTMLParser.cpp: (WebCore::HTMLParser::HTMLParser): Changed to use member construction syntax instead of calling reset(). This is especially helpful in the fragment case, where calling reset() later on is illegal, so not using it in the constructor lets us assert. (WebCore::HTMLParser::~HTMLParser): Did an explicit deref instead of calling setCurrent for its side effect. (WebCore::HTMLParser::reset): Updated for member name changes and removal and to use document instead of doc(). (WebCore::HTMLParser::setCurrent): Use document instead of doc(). (WebCore::HTMLParser::setSkipMode): Added. No longer inline. Now sets the m_inCanvasBeforeFirstOpenTag data member to false. (WebCore::HTMLParser::parseToken): Tightened up the skip mode logic at the top of the function, and added a FIXME about the strange case there where we don't skip yet stay in skip mode. Updated for renaming and doc(). (WebCore::HTMLParser::insertNode): Updated for renaming and doc(). (WebCore::HTMLParser::handleError): Ditto. (WebCore::HTMLParser::framesetCreateErrorCheck): Ditto. (WebCore::HTMLParser::isindexCreateErrorCheck): Changed to use RefPtr. (WebCore::HTMLParser::noscriptCreateErrorCheck): Updated for renaming and doc(). (WebCore::HTMLParser::mapCreateErrorCheck): Ditto. (WebCore::HTMLParser::getNode): Removed the special case for canvas here. Canvas fallback is now handled in the DOM, not the parser. Updated for renaming and doc(). (WebCore::HTMLParser::allowNestedRedundantTag): Changed a #define into a C++ constant. (WebCore::HTMLParser::processCloseTag): Updated for renaming and doc(). (WebCore::HTMLParser::isInline): Ditto. (WebCore::HTMLParser::tagIsOnStack): Added. Used by new canvas logic. (WebCore::HTMLParser::popBlock): Updated for renaming and doc(). Also renamed the local variable Elem to elem. (WebCore::HTMLParser::createHead): Ditto. (WebCore::HTMLParser::handleIsindex): Changed to use RefPtr. (WebCore::HTMLParser::startBody): Updated for renaming and doc(). (WebCore::HTMLParser::finished): Ditto.
Location:
trunk
Files:
12 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r20166 r20170  
     12007-03-13  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Maciej.
     4
     5        - tests for http://bugs.webkit.org/show_bug.cgi?id=12794
     6          <rdar://problem/5028154> REGRESSION: TripTik planner at aaa.com never
     7          finishes loading due to unclosed canvas tag (12794)
     8
     9        * fast/canvas/canvas-hides-fallback-expected.txt: Added.
     10        * fast/canvas/canvas-hides-fallback.html: Added.
     11        * fast/canvas/script-inside-canvas-fallback-expected.txt: Added.
     12        * fast/canvas/script-inside-canvas-fallback.html: Added.
     13        * fast/canvas/unclosed-canvas-1-expected.txt: Added.
     14        * fast/canvas/unclosed-canvas-1.html: Added.
     15        * fast/canvas/unclosed-canvas-2-expected.txt: Added.
     16        * fast/canvas/unclosed-canvas-2.html: Added.
     17        * fast/canvas/unclosed-canvas-3-expected.txt: Added.
     18        * fast/canvas/unclosed-canvas-3.html: Added.
     19        * fast/canvas/unclosed-canvas-4-expected.txt: Added.
     20        * fast/canvas/unclosed-canvas-4.html: Added.
     21
    1222007-03-13  David Harrison  <harrison@apple.com>
    223
  • trunk/WebCore/ChangeLog

    r20169 r20170  
     12007-03-13  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Maciej.
     4
     5        - fix http://bugs.webkit.org/show_bug.cgi?id=12794
     6          <rdar://problem/5028154> REGRESSION: TripTik planner at aaa.com never
     7          finishes loading due to unclosed canvas tag (12794)
     8
     9        Change <canvas> elements so that their contents are parsed normally,
     10        but not rendered. This change fixes the bug, because normal parsing
     11        rules close the <canvas> element in that case. The special parser
     12        stuff was just getting in the way.
     13
     14        Also do some basic cleanup to the HTML parser. This was motivated by
     15        an earlier version of this patch that made even more changes to the
     16        parser, but the cleanup is still worth landing.
     17
     18        Test: fast/canvas/canvas-hides-fallback.html
     19        Test: fast/canvas/script-inside-canvas-fallback.html
     20        Test: fast/canvas/unclosed-canvas-1.html
     21        Test: fast/canvas/unclosed-canvas-2.html
     22        Test: fast/canvas/unclosed-canvas-3.html
     23        Test: fast/canvas/unclosed-canvas-4.html
     24
     25        * html/HTMLCanvasElement.h: Added a data member to keep track of whether the
     26        renderer is a RenderHTMLCanvas or not.
     27        * html/HTMLCanvasElement.cpp:
     28        (WebCore::HTMLCanvasElement::createRenderer): If JavaScript is enabled, create
     29        a RenderHTMLCanvas. If it's not, let the default code create the default type
     30        of renderer, which will result in fallback content being visible. The
     31        RenderHTMLCanvas class already hides all of its children. Set the m_rendererIsCanvas
     32        boolean accordingly. Since the actual storage for the canvas is allocated lazily
     33        when you actually get a drawing context, we don't need to do anything special
     34        to prevent it when JavaScript is disabled; the relevant functions won't be called.
     35        (WebCore::HTMLCanvasElement::reset): Protect the code that manipulates the
     36        RenderHTMLCanvas with a check of m_rendererIsCanvas. This is the only code inside
     37        the DOM element that relies on the renderer type.
     38
     39        * html/HTMLParser.h: Removed unneeded includes. Marked HTMLParser as
     40        Noncopyable. Changed the Document parameter to the constructor to instead
     41        of HTMLDocument. Renamed discard_until to m_skipModeTag for clarity.
     42        Removed unused noSpaces function and unneeded public doc() function.
     43        Moved data members all down to the end so you can see them together in order.
     44        Renamed map to m_currentMapElement and isindex to m_isindexElement.
     45        Removed unused end and headLoaded data members.  Renamed m_fragment to
     46        m_isParsingFragment to make it clearer that it's a boolean, not a fragment.
     47
     48        * html/HTMLParser.cpp:
     49        (WebCore::HTMLParser::HTMLParser): Changed to use member construction
     50        syntax instead of calling reset(). This is especially helpful in the
     51        fragment case, where calling reset() later on is illegal, so not using
     52        it in the constructor lets us assert.
     53        (WebCore::HTMLParser::~HTMLParser): Did an explicit deref instead of
     54        calling setCurrent for its side effect.
     55        (WebCore::HTMLParser::reset): Updated for member name changes and removal
     56        and to use document instead of doc().
     57        (WebCore::HTMLParser::setCurrent): Use document instead of doc().
     58        (WebCore::HTMLParser::setSkipMode): Added. No longer inline. Now sets the
     59        m_inCanvasBeforeFirstOpenTag data member to false.
     60        (WebCore::HTMLParser::parseToken): Tightened up the skip mode logic at the
     61        top of the function, and added a FIXME about the strange case there where
     62        we don't skip yet stay in skip mode. Updated for renaming and doc().
     63        (WebCore::HTMLParser::insertNode): Updated for renaming and doc().
     64        (WebCore::HTMLParser::handleError): Ditto.
     65        (WebCore::HTMLParser::framesetCreateErrorCheck): Ditto.
     66        (WebCore::HTMLParser::isindexCreateErrorCheck): Changed to use RefPtr.
     67        (WebCore::HTMLParser::noscriptCreateErrorCheck): Updated for renaming and doc().
     68        (WebCore::HTMLParser::mapCreateErrorCheck): Ditto.
     69        (WebCore::HTMLParser::getNode): Removed the special case for canvas here.
     70        Canvas fallback is now handled in the DOM, not the parser. Updated for
     71        renaming and doc().
     72        (WebCore::HTMLParser::allowNestedRedundantTag): Changed a #define into a C++
     73        constant.
     74        (WebCore::HTMLParser::processCloseTag): Updated for renaming and doc().
     75        (WebCore::HTMLParser::isInline): Ditto.
     76        (WebCore::HTMLParser::tagIsOnStack): Added. Used by new canvas logic.
     77        (WebCore::HTMLParser::popBlock): Updated for renaming and doc(). Also renamed
     78        the local variable Elem to elem.
     79        (WebCore::HTMLParser::createHead): Ditto.
     80        (WebCore::HTMLParser::handleIsindex): Changed to use RefPtr.
     81        (WebCore::HTMLParser::startBody): Updated for renaming and doc().
     82        (WebCore::HTMLParser::finished): Ditto.
     83
    1842007-03-13  David Hyatt  <hyatt@apple.com>
    285
  • trunk/WebCore/html/HTMLCanvasElement.cpp

    r19876 r20170  
    11/*
    2  * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
     2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3131#include "CanvasRenderingContext2D.h"
    3232#include "CanvasStyle.h"
     33#include "Chrome.h"
    3334#include "Document.h"
    3435#include "Frame.h"
     
    3738#include "Page.h"
    3839#include "RenderHTMLCanvas.h"
    39 #include "Chrome.h"
    4040#include "Settings.h"
    41 #include "Screen.h"
    4241#include <math.h>
    4342
     
    9695}
    9796
    98 RenderObject* HTMLCanvasElement::createRenderer(RenderArena *arena, RenderStyle *style)
    99 {
    100     RenderHTMLCanvas* r = new (arena) RenderHTMLCanvas(this);
    101     r->setIntrinsicWidth(width());
    102     r->setIntrinsicHeight(height());
    103     return r;
     97RenderObject* HTMLCanvasElement::createRenderer(RenderArena* arena, RenderStyle* style)
     98{
     99    if (document()->frame() && document()->frame()->settings()->isJavaScriptEnabled()) {
     100        m_rendererIsCanvas = true;
     101        RenderHTMLCanvas* r = new (arena) RenderHTMLCanvas(this);
     102        r->setIntrinsicWidth(width());
     103        r->setIntrinsicHeight(height());
     104        return r;
     105    }
     106
     107    m_rendererIsCanvas = false;
     108    return HTMLElement::createRenderer(arena, style);
    104109}
    105110
     
    145150    m_size = IntSize(w, h);
    146151
    147     RenderHTMLCanvas* r = static_cast<RenderHTMLCanvas*>(renderer());
    148     if (r) {
    149         r->setIntrinsicWidth(w);
    150         r->setIntrinsicHeight(h);
    151         r->repaint();
    152     }
     152    if (RenderObject* ro = renderer())
     153        if (m_rendererIsCanvas) {
     154            RenderHTMLCanvas* r = static_cast<RenderHTMLCanvas*>(ro);
     155            r->setIntrinsicWidth(w);
     156            r->setIntrinsicHeight(h);
     157            r->repaint();
     158        }
    153159
    154160    m_createdDrawingContext = false;
  • trunk/WebCore/html/HTMLCanvasElement.h

    r18874 r20170  
    7777    void reset();
    7878
     79    bool m_rendererIsCanvas;
     80
    7981    RefPtr<CanvasRenderingContext2D> m_2DContext;
    8082    IntSize m_size;
  • trunk/WebCore/html/HTMLParser.cpp

    r20127 r20170  
    11/*
    2     This file is part of the KDE libraries
    3 
    42    Copyright (C) 1997 Martin Jones (mjones@kde.org)
    53              (C) 1997 Torben Weis (weis@kde.org)
    64              (C) 1999,2001 Lars Knoll (knoll@kde.org)
    75              (C) 2000,2001 Dirk Mueller (mueller@kde.org)
    8     Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
     6    Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    97
    108    This library is free software; you can redistribute it and/or
     
    3432#include "Frame.h"
    3533#include "HTMLBodyElement.h"
    36 #include "HTMLCanvasElement.h"
     34#include "HTMLDocument.h"
    3735#include "HTMLDivElement.h"
    3836#include "HTMLDListElement.h"
     
    5755using namespace HTMLNames;
    5856
    59 /**
    60  * @internal
    61  */
    62 
    63 class HTMLStackElem
    64 {
    65 public:
     57const int maxRedundantTagDepth = 20;
     58
     59struct HTMLStackElem : Noncopyable {
    6660    HTMLStackElem(const AtomicString& t, int lvl, Node* n, bool r, HTMLStackElem* nx)
    6761        : tagName(t)
     
    8983
    9084/**
    91  * @internal
     85 * The parser parses tokenized input into the document, building up the
     86 * document tree. If the document is well-formed, parsing it is straightforward.
    9287 *
    93  * The parser parses tokenized input into the document, building up the
    94  * document tree. If the document is wellformed, parsing it is
    95  * straightforward.
    96  * Unfortunately, people can't write wellformed HTML documents, so the parser
    97  * has to be tolerant about errors.
     88 * Unfortunately, we have to handle many HTML documents that are not well-formed,
     89 * so the parser has to be tolerant about errors.
    9890 *
    99  * We have to take care of the following error conditions:
     91 * We have to take care of at least the following error conditions:
     92 *
    10093 * 1. The element being added is explicitly forbidden inside some outer tag.
    10194 *    In this case we should close all tags up to the one, which forbids
    10295 *    the element, and add it afterwards.
    103  * 2. We are not allowed to add the element directly. It could be, that
    104  *    the person writing the document forgot some tag inbetween (or that the
    105  *    tag inbetween is optional...) This could be the case with the following
    106  *    tags: HTML HEAD BODY TBODY TR TD LI (did I forget any?)
    107  * 3. We wan't to add a block element inside to an inline element. Close all
     96 *
     97 * 2. We are not allowed to add the element directly. It could be that
     98 *    the person writing the document forgot some tag in between (or that the
     99 *    tag in between is optional). This could be the case with the following
     100 *    tags: HTML HEAD BODY TBODY TR TD LI (did I forget any?).
     101 *
     102 * 3. We want to add a block element inside to an inline element. Close all
    108103 *    inline elements up to the next higher block element.
    109  * 4. If this doesn't help close elements, until we are allowed to add the
     104 *
     105 * 4. If this doesn't help, close elements until we are allowed to add the
    110106 *    element or ignore the tag.
    111107 *
    112108 */
    113 HTMLParser::HTMLParser(Document* doc)
     109
     110HTMLParser::HTMLParser(HTMLDocument* doc)
    114111    : document(doc)
    115     , current(0)
     112    , current(doc)
    116113    , didRefCurrent(false)
    117114    , blockStack(0)
    118     , m_fragment(false)
    119 {
    120     reset();
     115    , form(0)
     116    , m_currentMapElement(0)
     117    , head(0)
     118    , inBody(false)
     119    , haveContent(false)
     120    , haveFrameSet(false)
     121    , m_isParsingFragment(false)
     122    , inStrayTableContent(0)
     123{
    121124}
    122125
    123126HTMLParser::HTMLParser(DocumentFragment* frag)
    124127    : document(frag->document())
    125     , current(0)
    126     , didRefCurrent(false)
     128    , current(frag)
     129    , didRefCurrent(true)
    127130    , blockStack(0)
    128     , m_fragment(true)
    129 {
    130     reset();
    131     setCurrent(frag);
    132     inBody = true;
     131    , form(0)
     132    , m_currentMapElement(0)
     133    , head(0)
     134    , inBody(true)
     135    , haveContent(false)
     136    , haveFrameSet(false)
     137    , m_isParsingFragment(true)
     138    , inStrayTableContent(0)
     139{
     140    if (frag)
     141        frag->ref();
    133142}
    134143
     
    136145{
    137146    freeBlock();
    138 
    139     setCurrent(0);
     147    if (didRefCurrent)
     148        current->deref();
    140149}
    141150
    142151void HTMLParser::reset()
    143152{
    144     setCurrent(doc());
     153    ASSERT(!m_isParsingFragment);
     154
     155    setCurrent(document);
    145156
    146157    freeBlock();
     
    150161    haveContent = false;
    151162    inStrayTableContent = 0;
    152    
     163
    153164    form = 0;
    154     map = 0;
     165    m_currentMapElement = 0;
    155166    head = 0;
    156     end = false;
    157     isindex = 0;
    158    
    159     discard_until = nullAtom;
     167    m_isindexElement = 0;
     168
     169    m_skipModeTag = nullAtom;
    160170}
    161171
    162172void HTMLParser::setCurrent(Node* newCurrent)
    163173{
    164     bool didRefNewCurrent = newCurrent && newCurrent != doc();
     174    bool didRefNewCurrent = newCurrent && newCurrent != document;
    165175    if (didRefNewCurrent)
    166176        newCurrent->ref();
     
    171181}
    172182
    173 PassRefPtr<Node> HTMLParser::parseToken(Token *t)
    174 {
    175     if (!discard_until.isNull()) {
    176         if (t->tagName == discard_until && !t->beginTag)
    177             discard_until = nullAtom;
    178 
    179         // do not skip </iframe>
    180         if (!discard_until.isNull() || (current->localName() != t->tagName))
     183PassRefPtr<Node> HTMLParser::parseToken(Token* t)
     184{
     185    if (!m_skipModeTag.isNull()) {
     186        if (!t->beginTag && t->tagName == m_skipModeTag)
     187            // Found the end tag for the current skip mode, so we're done skipping.
     188            m_skipModeTag = nullAtom;
     189        else if (current->localName() == t->tagName)
     190            // Do not skip </iframe>.
     191            // FIXME: What does that comment mean? How can it be right to parse a token without clearing m_skipModeTag?
     192            ;
     193        else
    181194            return 0;
    182195    }
    183196
    184     // Apparently some sites use </br> instead of <br>.  Be compatible with IE and Firefox and treat this like <br>.
    185     if (t->isCloseTag(brTag) && doc()->inCompatMode())
     197    // Apparently some sites use </br> instead of <br>. Be compatible with IE and Firefox and treat this like <br>.
     198    if (t->isCloseTag(brTag) && document->inCompatMode())
    186199        t->beginTag = true;
    187200
     
    236249        }
    237250
    238         if (map == n)
    239             map = 0;
     251        if (m_currentMapElement == n)
     252            m_currentMapElement = 0;
    240253
    241254        if (form == n)
     
    266279}
    267280
    268 bool HTMLParser::insertNode(Node *n, bool flat)
     281bool HTMLParser::insertNode(Node* n, bool flat)
    269282{
    270283    RefPtr<Node> protectNode(n);
     
    295308            didRefCurrent = true;
    296309        }
    297         if (parentAttached && !n->attached() && !m_fragment)
     310        if (parentAttached && !n->attached() && !m_isParsingFragment)
    298311            n->attach();
    299312    } else {
    300         if (parentAttached && !n->attached() && !m_fragment)
     313        if (parentAttached && !n->attached() && !m_isParsingFragment)
    301314            n->attach();
    302315        n->closeRenderer();
     
    309322{
    310323    // Error handling code.  This is just ad hoc handling of specific parent/child combinations.
    311     HTMLElement *e;
     324    HTMLElement* e;
    312325    bool handled = false;
    313326
     
    333346            if (head) {
    334347                if (head->addChild(n)) {
    335                     if (!n->attached() && !m_fragment)
     348                    if (!n->attached() && !m_isParsingFragment)
    336349                        n->attach();
    337350                    return true;
     
    341354        } else if (h->hasLocalName(htmlTag)) {
    342355            if (!current->isDocumentNode() ) {
    343                 if (doc()->firstChild()->hasTagName(htmlTag)) {
     356                if (document->firstChild()->hasTagName(htmlTag)) {
    344357                    // we have another <HTML> element.... apply attributes to existing one
    345358                    // make sure we don't overwrite already existing attributes
    346                     NamedAttrMap *map = static_cast<Element*>(n)->attributes(true);
    347                     Element *existingHTML = static_cast<Element*>(doc()->firstChild());
    348                     NamedAttrMap *bmap = existingHTML->attributes(false);
     359                    NamedAttrMap* map = static_cast<Element*>(n)->attributes(true);
     360                    Element* existingHTML = static_cast<Element*>(document->firstChild());
     361                    NamedAttrMap* bmap = existingHTML->attributes(false);
    349362                    for (unsigned l = 0; map && l < map->length(); ++l) {
    350363                        Attribute* it = map->attributeItem(l);
     
    366379                pushBlock(localName, tagPriority);
    367380                setCurrent(newNode);
    368                 if (!n->attached() && !m_fragment)
     381                if (!n->attached() && !m_isParsingFragment)
    369382                    n->attach();
    370383                return true;
     
    375388            }
    376389        } else if (h->hasLocalName(bodyTag)) {
    377             if (inBody && doc()->body()) {
     390            if (inBody && document->body()) {
    378391                // we have another <BODY> element.... apply attributes to existing one
    379392                // make sure we don't overwrite already existing attributes
    380393                // some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor>
    381                 NamedAttrMap *map = static_cast<Element*>(n)->attributes(true);
    382                 Element *existingBody = doc()->body();
    383                 NamedAttrMap *bmap = existingBody->attributes(false);
     394                NamedAttrMap* map = static_cast<Element*>(n)->attributes(true);
     395                Element* existingBody = document->body();
     396                NamedAttrMap* bmap = existingBody->attributes(false);
    384397                for (unsigned l = 0; map && l < map->length(); ++l) {
    385398                    Attribute* it = map->attributeItem(l);
     
    394407            if (equalIgnoringCase(h->getAttribute(typeAttr), "hidden") && form) {
    395408                form->addChild(n);
    396                 if (!n->attached() && !m_fragment)
     409                if (!n->attached() && !m_isParsingFragment)
    397410                    n->attach();
    398411                return true;
     
    405418            }
    406419        } else if (h->hasLocalName(areaTag)) {
    407             if (map) {
    408                 map->addChild(n);
    409                 if (!n->attached() && !m_fragment)
     420            if (m_currentMapElement) {
     421                m_currentMapElement->addChild(n);
     422                if (!n->attached() && !m_isParsingFragment)
    410423                    n->attach();
    411424                handled = true;
     
    443456        if (head) {
    444457            head->addChild(n);
    445             if (!n->attached() && !m_fragment)
     458            if (!n->attached() && !m_isParsingFragment)
    446459                n->attach();
    447460        }
     
    468481            } else {
    469482                if (n->isTextNode()) {
    470                     Text *t = static_cast<Text *>(n);
     483                    Text* t = static_cast<Text*>(n);
    471484                    if (t->containsOnlyWhitespace())
    472485                        return false;
     
    509522                ExceptionCode ec = 0;
    510523                if (n->isTextNode()) {
    511                     Text *t = static_cast<Text *>(n);
     524                    Text* t = static_cast<Text*>(n);
    512525                    if (t->containsOnlyWhitespace())
    513526                        return false;
    514                     StringImpl *i = t->string();
     527                    StringImpl* i = t->string();
    515528                    unsigned int pos = 0;
    516529                    while (pos < i->length() && ((*i)[pos] == ' ' || (*i)[pos] == noBreakSpace))
     
    520533                }
    521534                if (possiblyMoveStrayContent) {
    522                     Node *node = current;
    523                     Node *parent = node->parentNode();
     535                    Node* node = current;
     536                    Node* parent = node->parentNode();
    524537                    // A script may have removed the current node's parent from the DOM
    525538                    // http://bugs.webkit.org/show_bug.cgi?id=7137
     
    527540                    if (!parent)
    528541                        return false;
    529                     Node *grandparent = parent->parentNode();
     542                    Node* grandparent = parent->parentNode();
    530543
    531544                    if (n->isTextNode() ||
     
    537550                        node = (node->hasTagName(tableTag)) ? node :
    538551                                ((node->hasTagName(trTag)) ? grandparent : parent);
    539                         Node *parent = node->parentNode();
     552                        Node* parent = node->parentNode();
    540553                        if (!parent)
    541554                            return false;
     
    659672        // regressions and the headaches are not worth the work as long as there is
    660673        // no site actually relying on that detail (Dirk)
    661         if (doc()->body())
    662             doc()->body()->setAttribute(styleAttr, "display:none");
     674        if (document->body())
     675            document->body()->setAttribute(styleAttr, "display:none");
    663676        inBody = false;
    664677    }
     
    690703bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result)
    691704{
    692     Node *n = handleIsindex(t);
     705    RefPtr<Node> n = handleIsindex(t);
    693706    if (!inBody) {
    694         isindex = n;
     707        m_isindexElement = n.release();
    695708    } else {
    696709        t->flat = true;
    697         result = n;
     710        result = n.release();
    698711    }
    699712    return false;
     
    759772bool HTMLParser::noscriptCreateErrorCheck(Token* t, RefPtr<Node>& result)
    760773{
    761     if (!m_fragment && document->frame() && document->frame()->settings()->isJavaScriptEnabled())
     774    if (!m_isParsingFragment && document->frame() && document->frame()->settings()->isJavaScriptEnabled())
    762775        setSkipMode(noscriptTag);
    763776    return true;
     
    766779bool HTMLParser::mapCreateErrorCheck(Token* t, RefPtr<Node>& result)
    767780{
    768     map = new HTMLMapElement(document);
    769     result = map;
     781    m_currentMapElement = new HTMLMapElement(document);
     782    result = m_currentMapElement;
    770783    return false;
    771 }
    772 
    773 bool HTMLParser::canvasCreateErrorCheck(Token* t, RefPtr<Node>& result)
    774 {
    775     if (document->frame() && document->frame()->settings()->usesDashboardBackwardCompatibilityMode())
    776         return true;
    777 
    778     if (!m_fragment && document->frame() && document->frame()->settings()->isJavaScriptEnabled())
    779         setSkipMode(canvasTag);
    780     return true;
    781784}
    782785
     
    791794        gFunctionMap.set(bodyTag.localName().impl(), &HTMLParser::bodyCreateErrorCheck);
    792795        gFunctionMap.set(buttonTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck);
    793         gFunctionMap.set(canvasTag.localName().impl(), &HTMLParser::canvasCreateErrorCheck);
    794796        gFunctionMap.set(commentAtom.impl(), &HTMLParser::commentCreateErrorCheck);
    795797        gFunctionMap.set(ddTag.localName().impl(), &HTMLParser::ddCreateErrorCheck);
     
    828830        proceed = (this->*errorCheckFunc)(t, result);
    829831    if (proceed)
    830         result = HTMLElementFactory::createHTMLElement(t->tagName, doc(), form);
     832        result = HTMLElementFactory::createHTMLElement(t->tagName, document, form);
    831833    return result.release();
    832834}
    833835
    834 #define MAX_REDUNDANT 20
    835 
    836 bool HTMLParser::allowNestedRedundantTag(const AtomicString& _tagName)
     836bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName)
    837837{
    838838    // www.liceo.edu.mx is an example of a site that achieves a level of nesting of
     
    841841    int i = 0;
    842842    for (HTMLStackElem* curr = blockStack;
    843          i < MAX_REDUNDANT && curr && curr->tagName == _tagName;
     843         i < maxRedundantTagDepth && curr && curr->tagName == tagName;
    844844         curr = curr->next, i++);
    845     return i != MAX_REDUNDANT;
    846 }
    847 
    848 void HTMLParser::processCloseTag(Token *t)
     845    return i != maxRedundantTagDepth;
     846}
     847
     848void HTMLParser::processCloseTag(Token* t)
    849849{
    850850    // Support for really broken html.
     
    857857        form = 0;
    858858    else if (t->tagName == mapTag)
    859         map = 0;
     859        m_currentMapElement = 0;
    860860       
    861861    HTMLStackElem* oldElem = blockStack;
     
    917917            e->hasLocalName(supTag) || e->hasLocalName(spanTag) || e->hasLocalName(nobrTag) ||
    918918            e->hasLocalName(wbrTag) || e->hasLocalName(noframesTag) || e->hasLocalName(nolayerTag) ||
    919             e->hasLocalName(noembedTag) || (e->hasLocalName(noscriptTag) && !m_fragment && document->frame() && document->frame()->settings()->isJavaScriptEnabled()))
     919            e->hasLocalName(noembedTag) || (e->hasLocalName(noscriptTag) && !m_isParsingFragment && document->frame() && document->frame()->settings()->isJavaScriptEnabled()))
    920920            return true;
    921921    }
     
    12081208}
    12091209
    1210 void HTMLParser::popBlock(const AtomicString& _tagName)
    1211 {
    1212     HTMLStackElem *Elem = blockStack;
     1210void HTMLParser::popBlock(const AtomicString& tagName)
     1211{
     1212    HTMLStackElem* elem = blockStack;
    12131213   
    12141214    int maxLevel = 0;
    12151215
    1216     while (Elem && (Elem->tagName != _tagName)) {
    1217         if (maxLevel < Elem->level)
    1218             maxLevel = Elem->level;
    1219         Elem = Elem->next;
    1220     }
    1221 
    1222     if (!Elem)
     1216    while (elem && (elem->tagName != tagName)) {
     1217        if (maxLevel < elem->level)
     1218            maxLevel = elem->level;
     1219        elem = elem->next;
     1220    }
     1221
     1222    if (!elem)
    12231223        return;
    12241224
    1225     if (maxLevel > Elem->level) {
     1225    if (maxLevel > elem->level) {
    12261226        // We didn't match because the tag is in a different scope, e.g.,
    12271227        // <b><p>Foo</b>.  Try to correct the problem.
    1228         if (!isResidualStyleTag(_tagName))
     1228        if (!isResidualStyleTag(tagName))
    12291229            return;
    1230         return handleResidualStyleCloseTagAcrossBlocks(Elem);
    1231     }
    1232 
    1233     bool isAffectedByStyle = isAffectedByResidualStyle(Elem->tagName);
     1230        return handleResidualStyleCloseTagAcrossBlocks(elem);
     1231    }
     1232
     1233    bool isAffectedByStyle = isAffectedByResidualStyle(elem->tagName);
    12341234    HTMLStackElem* residualStyleStack = 0;
    12351235    Node* malformedTableParent = 0;
    12361236   
    1237     Elem = blockStack;
    1238     while (Elem) {
    1239         if (Elem->tagName == _tagName) {
     1237    elem = blockStack;
     1238    while (elem) {
     1239        if (elem->tagName == tagName) {
    12401240            int strayTable = inStrayTableContent;
    12411241            popOneBlock();
    1242             Elem = 0;
     1242            elem = 0;
    12431243
    12441244            // This element was the root of some malformed content just inside an implicit or
     
    12541254        }
    12551255        else {
    1256             if (form && Elem->tagName == formTag)
     1256            if (form && elem->tagName == formTag)
    12571257                // A <form> is being closed prematurely (and this is
    12581258                // malformed HTML).  Set an attribute on the form to clear out its
     
    12621262            // Schedule this tag for reopening
    12631263            // after we complete the close of this entire block.
    1264             if (isAffectedByStyle && isResidualStyleTag(Elem->tagName))
     1264            if (isAffectedByStyle && isResidualStyleTag(elem->tagName))
    12651265                // We've overloaded the use of stack elements and are just reusing the
    12661266                // struct with a slightly different meaning to the variables.  Instead of chaining
     
    12681268                // from the outermost to the innermost, i.e., residualStyleStack will end up pointing
    12691269                // to the outermost tag we need to reopen.
    1270                 // We also set Elem->node to be the actual element that corresponds to the ID stored in
    1271                 // Elem->id rather than the node that you should pop to when the element gets pulled off
     1270                // We also set elem->node to be the actual element that corresponds to the ID stored in
     1271                // elem->id rather than the node that you should pop to when the element gets pulled off
    12721272                // the stack.
    12731273                moveOneBlockToStack(residualStyleStack);
    12741274            else
    12751275                popOneBlock();
    1276             Elem = blockStack;
     1276            elem = blockStack;
    12771277        }
    12781278    }
     
    13481348void HTMLParser::createHead()
    13491349{
    1350     if (head || !doc()->firstChild())
     1350    if (head || !document->firstChild())
    13511351        return;
    13521352
    13531353    head = new HTMLHeadElement(document);
    1354     HTMLElement* body = doc()->body();
     1354    HTMLElement* body = document->body();
    13551355    ExceptionCode ec = 0;
    1356     doc()->firstChild()->insertBefore(head, body, ec);
     1356    document->firstChild()->insertBefore(head, body, ec);
    13571357    if (ec)
    13581358        head = 0;
    13591359}
    13601360
    1361 Node* HTMLParser::handleIsindex(Token* t)
    1362 {
    1363     Node* n = new HTMLDivElement(document);
     1361PassRefPtr<Node> HTMLParser::handleIsindex(Token* t)
     1362{
     1363    RefPtr<Node> n = new HTMLDivElement(document);
    13641364
    13651365    NamedMappedAttrMap* attrs = t->attrs.get();
     
    13711371    String text = searchableIndexIntroduction();
    13721372    if (attrs) {
    1373         if (Attribute *a = attrs->getAttributeItem(promptAttr))
     1373        if (Attribute* a = attrs->getAttributeItem(promptAttr))
    13741374            text = a->value().domString() + " ";
    13751375        t->attrs = 0;
     
    13781378    n->addChild(new HTMLHRElement(document));
    13791379    n->addChild(new Text(document, text));
    1380     n->addChild(isIndex.get());
     1380    n->addChild(isIndex.release());
    13811381    n->addChild(new HTMLHRElement(document));
    13821382
    1383     return n;
     1383    return n.release();
    13841384}
    13851385
    13861386void HTMLParser::startBody()
    13871387{
    1388     if(inBody) return;
     1388    if (inBody)
     1389        return;
    13891390
    13901391    inBody = true;
    13911392
    1392     if (isindex) {
    1393         insertNode(isindex.get(), true /* don't decend into this node */);
    1394         isindex = 0;
     1393    if (m_isindexElement) {
     1394        insertNode(m_isindexElement.get(), true /* don't descend into this node */);
     1395        m_isindexElement = 0;
    13951396    }
    13961397}
     
    14071408
    14081409    // Warning, this may delete the tokenizer and parser, so don't try to do anything else after this.
    1409     if (!m_fragment)
     1410    if (!m_isParsingFragment)
    14101411        document->finishedParsing();
    14111412}
  • trunk/WebCore/html/HTMLParser.h

    r18874 r20170  
    11/*
    2     This file is part of the KDE libraries
    3 
    42    Copyright (C) 1997 Martin Jones (mjones@kde.org)
    53              (C) 1997 Torben Weis (weis@kde.org)
    64              (C) 1998 Waldo Bastian (bastian@kde.org)
    75              (C) 1999 Lars Knoll (knoll@kde.org)
    8     Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
     6    Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    97
    108    This library is free software; you can redistribute it and/or
     
    2321    Boston, MA 02111-1307, USA.
    2422*/
    25 //----------------------------------------------------------------------------
    26 //
    27 // KDE HTML Widget -- HTML Parser
    2823
    2924#ifndef HTMLParser_h
    3025#define HTMLParser_h
    3126
    32 #include "HTMLDocument.h"
     27#include "QualifiedName.h"
     28#include <wtf/Forward.h>
     29#include <wtf/RefPtr.h>
    3330
    3431namespace WebCore {
    3532
     33class Document;
    3634class DocumentFragment;
    37 class FrameView;
    38 class HTMLElement;
     35class HTMLDocument;
    3936class HTMLFormElement;
    4037class HTMLHeadElement;
    4138class HTMLMapElement;
    42 class HTMLStackElem;
     39class Node;
    4340class Token;
    4441
     42struct HTMLStackElem;
     43
    4544/**
    46  * The parser for html. It receives a stream of tokens from the HTMLTokenizer, and
    47  * builds up the Document structure form it.
     45 * The parser for HTML. It receives a stream of tokens from the HTMLTokenizer, and
     46 * builds up the Document structure from it.
    4847 */
    49 class HTMLParser
    50 {
     48class HTMLParser : Noncopyable {
    5149public:
    52     HTMLParser(Document*);
     50    HTMLParser(HTMLDocument*);
    5351    HTMLParser(DocumentFragment*);
    5452    virtual ~HTMLParser();
     
    6967    void reset();
    7068
    71     bool skipMode() const { return !discard_until.isNull(); }
    72     bool noSpaces() const { return !inBody; }
    73 
    74     HTMLDocument *doc() const { return static_cast<HTMLDocument *>(document); }
     69    bool skipMode() const { return !m_skipModeTag.isNull(); }
    7570
    7671private:
    77     void setCurrent(Node* newCurrent);
     72    void setCurrent(Node*);
    7873    void derefCurrent();
    79     void setSkipMode(const QualifiedName& qName) { discard_until = qName.localName(); }
    80 
    81     Document* document;
     74    void setSkipMode(const QualifiedName& qName) { m_skipModeTag = qName.localName(); }
    8275
    8376    PassRefPtr<Node> getNode(Token*);
     
    10497    bool textCreateErrorCheck(Token*, RefPtr<Node>&);
    10598
    106     void processCloseTag(Token *);
     99    void processCloseTag(Token*);
    107100
    108     bool insertNode(Node *n, bool flat = false);
    109     bool handleError(Node* n, bool flat, const AtomicString& localName, int tagPriority);
     101    bool insertNode(Node*, bool flat = false);
     102    bool handleError(Node*, bool flat, const AtomicString& localName, int tagPriority);
    110103   
    111     // The currently active element (the one new elements will be added to). Can be a document fragment, a document or an element.
    112     Node* current;
    113     // We can't ref a document, but we don't want to constantly check if a node is a document just to decide whether to deref.
    114     bool didRefCurrent;
    115 
    116     HTMLStackElem *blockStack;
    117 
    118     void pushBlock(const AtomicString& tagName, int _level);
     104    void pushBlock(const AtomicString& tagName, int level);
    119105    void popBlock(const AtomicString& tagName);
    120106    void popBlock(const QualifiedName& qName) { return popBlock(qName.localName()); } // Convenience function for readability.
     
    128114    void createHead();
    129115
    130     bool isResidualStyleTag(const AtomicString& tagName);
    131     bool isAffectedByResidualStyle(const AtomicString& tagName);
     116    static bool isResidualStyleTag(const AtomicString& tagName);
     117    static bool isAffectedByResidualStyle(const AtomicString& tagName);
    132118    void handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem*);
    133119    void reopenResidualStyleTags(HTMLStackElem*, Node* malformedTableParent);
     
    138124    void popNestedHeaderTag();
    139125
    140     bool isInline(Node* node) const;
     126    bool isInline(Node*) const;
    141127   
    142     /*
    143      * currently active form
    144      */
    145     HTMLFormElement *form;
     128    void startBody(); // inserts the isindex element
     129    PassRefPtr<Node> handleIsindex(Token*);
    146130
    147     /*
    148      * current map
    149      */
    150     HTMLMapElement *map;
     131    Document* document;
    151132
    152     /*
    153      * the head element. Needed for crappy html which defines <base> after </head>
    154      */
    155     HTMLHeadElement *head;
     133    // The currently active element (the one new elements will be added to). Can be a document fragment, a document or an element.
     134    Node* current;
     135    // We can't ref a document, but we don't want to constantly check if a node is a document just to decide whether to deref.
     136    bool didRefCurrent;
    156137
    157     /*
    158      * a possible <isindex> element in the head. Compatibility hack for
    159      * html from the stone age
    160      */
    161     RefPtr<Node> isindex;
    162     Node* handleIsindex(Token*);
     138    HTMLStackElem* blockStack;
    163139
    164     /*
    165      * inserts the stupid isIndex element.
    166      */
    167     void startBody();
     140    HTMLFormElement* form; // currently active form
     141    HTMLMapElement* m_currentMapElement; // current map
     142    HTMLHeadElement* head; // head element; needed for HTML which defines <base> after </head>
     143    RefPtr<Node> m_isindexElement; // a possible <isindex> element in the head
    168144
    169145    bool inBody;
    170146    bool haveContent;
    171147    bool haveFrameSet;
    172     bool end;
    173148
    174     /*
    175      * tells the parser to discard all tags, until it reaches the one specified
    176      */
    177     AtomicString discard_until;
     149    AtomicString m_skipModeTag; // tells the parser to discard all tags until it reaches the one specified
    178150
    179     bool headLoaded;
    180     bool m_fragment;
     151    bool m_isParsingFragment;
    181152    int inStrayTableContent;
    182153};
Note: See TracChangeset for help on using the changeset viewer.