| OLD | NEW |
| 1 /* | 1 /* |
| 2 Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 Copyright (C) 1997 Martin Jones (mjones@kde.org) |
| 3 (C) 1997 Torben Weis (weis@kde.org) | 3 (C) 1997 Torben Weis (weis@kde.org) |
| 4 (C) 1999,2001 Lars Knoll (knoll@kde.org) | 4 (C) 1999,2001 Lars Knoll (knoll@kde.org) |
| 5 (C) 2000,2001 Dirk Mueller (mueller@kde.org) | 5 (C) 2000,2001 Dirk Mueller (mueller@kde.org) |
| 6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 6 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
| 7 | 7 |
| 8 This library is free software; you can redistribute it and/or | 8 This library is free software; you can redistribute it and/or |
| 9 modify it under the terms of the GNU Library General Public | 9 modify it under the terms of the GNU Library General Public |
| 10 License as published by the Free Software Foundation; either | 10 License as published by the Free Software Foundation; either |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 * | 106 * |
| 107 * 3. We want to add a block element inside to an inline element. Close all | 107 * 3. We want to add a block element inside to an inline element. Close all |
| 108 * inline elements up to the next higher block element. | 108 * inline elements up to the next higher block element. |
| 109 * | 109 * |
| 110 * 4. If this doesn't help, close elements until we are allowed to add the | 110 * 4. If this doesn't help, close elements until we are allowed to add the |
| 111 * element or ignore the tag. | 111 * element or ignore the tag. |
| 112 * | 112 * |
| 113 */ | 113 */ |
| 114 | 114 |
| 115 HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors) | 115 HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors) |
| 116 : document(doc) | 116 : m_document(doc) |
| 117 , current(doc) | 117 , m_current(doc) |
| 118 , didRefCurrent(false) | 118 , m_didRefCurrent(false) |
| 119 , blockStack(0) | 119 , m_blockStack(0) |
| 120 , m_hasPElementInScope(NotInScope) | 120 , m_hasPElementInScope(NotInScope) |
| 121 , head(0) | 121 , m_head(0) |
| 122 , inBody(false) | 122 , m_inBody(false) |
| 123 , haveContent(false) | 123 , m_haveContent(false) |
| 124 , haveFrameSet(false) | 124 , m_haveFrameSet(false) |
| 125 , m_isParsingFragment(false) | 125 , m_isParsingFragment(false) |
| 126 , m_reportErrors(reportErrors) | 126 , m_reportErrors(reportErrors) |
| 127 , m_handlingResidualStyleAcrossBlocks(false) | 127 , m_handlingResidualStyleAcrossBlocks(false) |
| 128 , inStrayTableContent(0) | 128 , m_inStrayTableContent(0) |
| 129 { | 129 { |
| 130 } | 130 } |
| 131 | 131 |
| 132 HTMLParser::HTMLParser(DocumentFragment* frag) | 132 HTMLParser::HTMLParser(DocumentFragment* frag) |
| 133 : document(frag->document()) | 133 : m_document(frag->document()) |
| 134 , current(frag) | 134 , m_current(frag) |
| 135 , didRefCurrent(true) | 135 , m_didRefCurrent(true) |
| 136 , blockStack(0) | 136 , m_blockStack(0) |
| 137 , m_hasPElementInScope(NotInScope) | 137 , m_hasPElementInScope(NotInScope) |
| 138 , head(0) | 138 , m_head(0) |
| 139 , inBody(true) | 139 , m_inBody(true) |
| 140 , haveContent(false) | 140 , m_haveContent(false) |
| 141 , haveFrameSet(false) | 141 , m_haveFrameSet(false) |
| 142 , m_isParsingFragment(true) | 142 , m_isParsingFragment(true) |
| 143 , m_reportErrors(false) | 143 , m_reportErrors(false) |
| 144 , m_handlingResidualStyleAcrossBlocks(false) | 144 , m_handlingResidualStyleAcrossBlocks(false) |
| 145 , inStrayTableContent(0) | 145 , m_inStrayTableContent(0) |
| 146 { | 146 { |
| 147 if (frag) | 147 if (frag) |
| 148 frag->ref(); | 148 frag->ref(); |
| 149 } | 149 } |
| 150 | 150 |
| 151 HTMLParser::~HTMLParser() | 151 HTMLParser::~HTMLParser() |
| 152 { | 152 { |
| 153 freeBlock(); | 153 freeBlock(); |
| 154 if (didRefCurrent) | 154 if (m_didRefCurrent) |
| 155 current->deref(); | 155 m_current->deref(); |
| 156 } | 156 } |
| 157 | 157 |
| 158 void HTMLParser::reset() | 158 void HTMLParser::reset() |
| 159 { | 159 { |
| 160 ASSERT(!m_isParsingFragment); | 160 ASSERT(!m_isParsingFragment); |
| 161 | 161 |
| 162 setCurrent(document); | 162 setCurrent(m_document); |
| 163 | 163 |
| 164 freeBlock(); | 164 freeBlock(); |
| 165 | 165 |
| 166 inBody = false; | 166 m_inBody = false; |
| 167 haveFrameSet = false; | 167 m_haveFrameSet = false; |
| 168 haveContent = false; | 168 m_haveContent = false; |
| 169 inStrayTableContent = 0; | 169 m_inStrayTableContent = 0; |
| 170 | 170 |
| 171 m_currentFormElement = 0; | 171 m_currentFormElement = 0; |
| 172 m_currentMapElement = 0; | 172 m_currentMapElement = 0; |
| 173 head = 0; | 173 m_head = 0; |
| 174 m_isindexElement = 0; | 174 m_isindexElement = 0; |
| 175 | 175 |
| 176 m_skipModeTag = nullAtom; | 176 m_skipModeTag = nullAtom; |
| 177 } | 177 } |
| 178 | 178 |
| 179 void HTMLParser::setCurrent(Node* newCurrent) | 179 void HTMLParser::setCurrent(Node* newCurrent) |
| 180 { | 180 { |
| 181 bool didRefNewCurrent = newCurrent && newCurrent != document; | 181 bool didRefNewCurrent = newCurrent && newCurrent != m_document; |
| 182 if (didRefNewCurrent) | 182 if (didRefNewCurrent) |
| 183 newCurrent->ref(); | 183 newCurrent->ref(); |
| 184 if (didRefCurrent) | 184 if (m_didRefCurrent) |
| 185 current->deref(); | 185 m_current->deref(); |
| 186 current = newCurrent; | 186 m_current = newCurrent; |
| 187 didRefCurrent = didRefNewCurrent; | 187 m_didRefCurrent = didRefNewCurrent; |
| 188 } | 188 } |
| 189 | 189 |
| 190 PassRefPtr<Node> HTMLParser::parseToken(Token* t) | 190 PassRefPtr<Node> HTMLParser::parseToken(Token* t) |
| 191 { | 191 { |
| 192 if (!m_skipModeTag.isNull()) { | 192 if (!m_skipModeTag.isNull()) { |
| 193 if (!t->beginTag && t->tagName == m_skipModeTag) | 193 if (!t->beginTag && t->tagName == m_skipModeTag) |
| 194 // Found the end tag for the current skip mode, so we're done skippi
ng. | 194 // Found the end tag for the current skip mode, so we're done skippi
ng. |
| 195 m_skipModeTag = nullAtom; | 195 m_skipModeTag = nullAtom; |
| 196 else if (current->localName() == t->tagName) | 196 else if (m_current->localName() == t->tagName) |
| 197 // Do not skip </iframe>. | 197 // Do not skip </iframe>. |
| 198 // FIXME: What does that comment mean? How can it be right to parse
a token without clearing m_skipModeTag? | 198 // FIXME: What does that comment mean? How can it be right to parse
a token without clearing m_skipModeTag? |
| 199 ; | 199 ; |
| 200 else | 200 else |
| 201 return 0; | 201 return 0; |
| 202 } | 202 } |
| 203 | 203 |
| 204 // Apparently some sites use </br> instead of <br>. Be compatible with IE an
d Firefox and treat this like <br>. | 204 // Apparently some sites use </br> instead of <br>. Be compatible with IE an
d Firefox and treat this like <br>. |
| 205 if (t->isCloseTag(brTag) && document->inCompatMode()) { | 205 if (t->isCloseTag(brTag) && m_document->inCompatMode()) { |
| 206 reportError(MalformedBRError); | 206 reportError(MalformedBRError); |
| 207 t->beginTag = true; | 207 t->beginTag = true; |
| 208 } | 208 } |
| 209 | 209 |
| 210 if (!t->beginTag) { | 210 if (!t->beginTag) { |
| 211 processCloseTag(t); | 211 processCloseTag(t); |
| 212 return 0; | 212 return 0; |
| 213 } | 213 } |
| 214 | 214 |
| 215 // Ignore spaces, if we're not inside a paragraph or other inline code. | 215 // Ignore spaces, if we're not inside a paragraph or other inline code. |
| 216 // Do not alter the text if it is part of a scriptTag. | 216 // Do not alter the text if it is part of a scriptTag. |
| 217 if (t->tagName == textAtom && t->text && current->localName() != scriptTag)
{ | 217 if (t->tagName == textAtom && t->text && m_current->localName() != scriptTag
) { |
| 218 if (inBody && !skipMode() && current->localName() != styleTag && | 218 if (m_inBody && !skipMode() && m_current->localName() != styleTag && |
| 219 current->localName() != titleTag && !t->text->containsOnlyWhitespace
()) | 219 m_current->localName() != titleTag && !t->text->containsOnlyWhitespa
ce()) |
| 220 haveContent = true; | 220 m_haveContent = true; |
| 221 | 221 |
| 222 RefPtr<Node> n; | 222 RefPtr<Node> n; |
| 223 String text = t->text.get(); | 223 String text = t->text.get(); |
| 224 unsigned charsLeft = text.length(); | 224 unsigned charsLeft = text.length(); |
| 225 while (charsLeft) { | 225 while (charsLeft) { |
| 226 // split large blocks of text to nodes of manageable size | 226 // split large blocks of text to nodes of manageable size |
| 227 n = Text::createWithLengthLimit(document, text, charsLeft); | 227 n = Text::createWithLengthLimit(m_document, text, charsLeft); |
| 228 if (!insertNode(n.get(), t->selfClosingTag)) | 228 if (!insertNode(n.get(), t->selfClosingTag)) |
| 229 return 0; | 229 return 0; |
| 230 } | 230 } |
| 231 return n; | 231 return n; |
| 232 } | 232 } |
| 233 | 233 |
| 234 RefPtr<Node> n = getNode(t); | 234 RefPtr<Node> n = getNode(t); |
| 235 // just to be sure, and to catch currently unimplemented stuff | 235 // just to be sure, and to catch currently unimplemented stuff |
| 236 if (!n) | 236 if (!n) |
| 237 return 0; | 237 return 0; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 262 Element* e = static_cast<Element*>(n.get()); | 262 Element* e = static_cast<Element*>(n.get()); |
| 263 e->setAttributeMap(0); | 263 e->setAttributeMap(0); |
| 264 } | 264 } |
| 265 | 265 |
| 266 if (m_currentMapElement == n) | 266 if (m_currentMapElement == n) |
| 267 m_currentMapElement = 0; | 267 m_currentMapElement = 0; |
| 268 | 268 |
| 269 if (m_currentFormElement == n) | 269 if (m_currentFormElement == n) |
| 270 m_currentFormElement = 0; | 270 m_currentFormElement = 0; |
| 271 | 271 |
| 272 if (head == n) | 272 if (m_head == n) |
| 273 head = 0; | 273 m_head = 0; |
| 274 | 274 |
| 275 return 0; | 275 return 0; |
| 276 } | 276 } |
| 277 return n; | 277 return n; |
| 278 } | 278 } |
| 279 | 279 |
| 280 void HTMLParser::parseDoctypeToken(DoctypeToken* t) | 280 void HTMLParser::parseDoctypeToken(DoctypeToken* t) |
| 281 { | 281 { |
| 282 // Ignore any doctype after the first. Ignore doctypes in fragments. | 282 // Ignore any doctype after the first. Ignore doctypes in fragments. |
| 283 if (document->doctype() || m_isParsingFragment || current != document) | 283 if (m_document->doctype() || m_isParsingFragment || m_current != m_document) |
| 284 return; | 284 return; |
| 285 | 285 |
| 286 // Make a new doctype node and set it as our doctype. | 286 // Make a new doctype node and set it as our doctype. |
| 287 document->addChild(DocumentType::create(document, String::adopt(t->m_name),
String::adopt(t->m_publicID), String::adopt(t->m_systemID))); | 287 m_document->addChild(DocumentType::create(m_document, String::adopt(t->m_nam
e), String::adopt(t->m_publicID), String::adopt(t->m_systemID))); |
| 288 } | 288 } |
| 289 | 289 |
| 290 static bool isTableSection(Node* n) | 290 static bool isTableSection(const Node* n) |
| 291 { | 291 { |
| 292 return n->hasTagName(tbodyTag) || n->hasTagName(tfootTag) || n->hasTagName(t
headTag); | 292 return n->hasTagName(tbodyTag) || n->hasTagName(tfootTag) || n->hasTagName(t
headTag); |
| 293 } | 293 } |
| 294 | 294 |
| 295 static bool isTablePart(Node* n) | 295 static bool isTablePart(const Node* n) |
| 296 { | 296 { |
| 297 return n->hasTagName(trTag) || n->hasTagName(tdTag) || n->hasTagName(thTag)
|| | 297 return n->hasTagName(trTag) || n->hasTagName(tdTag) || n->hasTagName(thTag)
|| |
| 298 isTableSection(n); | 298 isTableSection(n); |
| 299 } | 299 } |
| 300 | 300 |
| 301 static bool isTableRelated(Node* n) | 301 static bool isTableRelated(const Node* n) |
| 302 { | 302 { |
| 303 return n->hasTagName(tableTag) || isTablePart(n); | 303 return n->hasTagName(tableTag) || isTablePart(n); |
| 304 } | 304 } |
| 305 | 305 |
| 306 static bool isScopingTag(const AtomicString& tagName) | 306 static bool isScopingTag(const AtomicString& tagName) |
| 307 { | 307 { |
| 308 return tagName == appletTag || tagName == captionTag || tagName == tdTag ||
tagName == thTag || tagName == buttonTag || tagName == marqueeTag || tagName ==
objectTag || tagName == tableTag || tagName == htmlTag; | 308 return tagName == appletTag || tagName == captionTag || tagName == tdTag ||
tagName == thTag || tagName == buttonTag || tagName == marqueeTag || tagName ==
objectTag || tagName == tableTag || tagName == htmlTag; |
| 309 } | 309 } |
| 310 | 310 |
| 311 bool HTMLParser::insertNode(Node* n, bool flat) | 311 bool HTMLParser::insertNode(Node* n, bool flat) |
| 312 { | 312 { |
| 313 RefPtr<Node> protectNode(n); | 313 RefPtr<Node> protectNode(n); |
| 314 | 314 |
| 315 const AtomicString& localName = n->localName(); | 315 const AtomicString& localName = n->localName(); |
| 316 int tagPriority = n->isHTMLElement() ? static_cast<HTMLElement*>(n)->tagPrio
rity() : 0; | 316 int tagPriority = n->isHTMLElement() ? static_cast<HTMLElement*>(n)->tagPrio
rity() : 0; |
| 317 | 317 |
| 318 // <table> is never allowed inside stray table content. Always pop out of t
he stray table content | 318 // <table> is never allowed inside stray table content. Always pop out of t
he stray table content |
| 319 // and close up the first table, and then start the second table as a siblin
g. | 319 // and close up the first table, and then start the second table as a siblin
g. |
| 320 if (inStrayTableContent && localName == tableTag) | 320 if (m_inStrayTableContent && localName == tableTag) |
| 321 popBlock(tableTag); | 321 popBlock(tableTag); |
| 322 | 322 |
| 323 // let's be stupid and just try to insert it. | 323 // let's be stupid and just try to insert it. |
| 324 // this should work if the document is well-formed | 324 // this should work if the document is well-formed |
| 325 Node* newNode = current->addChild(n); | 325 Node* newNode = m_current->addChild(n); |
| 326 if (!newNode) | 326 if (!newNode) |
| 327 return handleError(n, flat, localName, tagPriority); // Try to handle th
e error. | 327 return handleError(n, flat, localName, tagPriority); // Try to handle th
e error. |
| 328 | 328 |
| 329 // don't push elements without end tags (e.g., <img>) on the stack | 329 // don't push elements without end tags (e.g., <img>) on the stack |
| 330 bool parentAttached = current->attached(); | 330 bool parentAttached = m_current->attached(); |
| 331 if (tagPriority > 0 && !flat) { | 331 if (tagPriority > 0 && !flat) { |
| 332 if (newNode == current) { | 332 if (newNode == m_current) { |
| 333 // This case should only be hit when a demoted <form> is placed insi
de a table. | 333 // This case should only be hit when a demoted <form> is placed insi
de a table. |
| 334 ASSERT(localName == formTag); | 334 ASSERT(localName == formTag); |
| 335 reportError(FormInsideTablePartError, ¤t->localName()); | 335 reportError(FormInsideTablePartError, &m_current->localName()); |
| 336 } else { | 336 } else { |
| 337 // The pushBlock function transfers ownership of current to the bloc
k stack | 337 // The pushBlock function transfers ownership of current to the bloc
k stack |
| 338 // so we're guaranteed that didRefCurrent is false. The code below i
s an | 338 // so we're guaranteed that m_didRefCurrent is false. The code below
is an |
| 339 // optimized version of setCurrent that takes advantage of that fact
and also | 339 // optimized version of setCurrent that takes advantage of that fact
and also |
| 340 // assumes that newNode is neither 0 nor a pointer to the document. | 340 // assumes that newNode is neither 0 nor a pointer to the document. |
| 341 pushBlock(localName, tagPriority); | 341 pushBlock(localName, tagPriority); |
| 342 newNode->beginParsingChildren(); | 342 newNode->beginParsingChildren(); |
| 343 ASSERT(!didRefCurrent); | 343 ASSERT(!m_didRefCurrent); |
| 344 newNode->ref(); | 344 newNode->ref(); |
| 345 current = newNode; | 345 m_current = newNode; |
| 346 didRefCurrent = true; | 346 m_didRefCurrent = true; |
| 347 } | 347 } |
| 348 if (parentAttached && !n->attached() && !m_isParsingFragment) | 348 if (parentAttached && !n->attached() && !m_isParsingFragment) |
| 349 n->attach(); | 349 n->attach(); |
| 350 } else { | 350 } else { |
| 351 if (parentAttached && !n->attached() && !m_isParsingFragment) | 351 if (parentAttached && !n->attached() && !m_isParsingFragment) |
| 352 n->attach(); | 352 n->attach(); |
| 353 n->finishParsingChildren(); | 353 n->finishParsingChildren(); |
| 354 } | 354 } |
| 355 | 355 |
| 356 if (localName == htmlTag && document->frame()) | 356 if (localName == htmlTag && m_document->frame()) |
| 357 document->frame()->loader()->dispatchDocumentElementAvailable(); | 357 m_document->frame()->loader()->dispatchDocumentElementAvailable(); |
| 358 | 358 |
| 359 return true; | 359 return true; |
| 360 } | 360 } |
| 361 | 361 |
| 362 bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
int tagPriority) | 362 bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
int tagPriority) |
| 363 { | 363 { |
| 364 // Error handling code. This is just ad hoc handling of specific parent/chi
ld combinations. | 364 // Error handling code. This is just ad hoc handling of specific parent/chi
ld combinations. |
| 365 HTMLElement* e; | 365 HTMLElement* e; |
| 366 bool handled = false; | 366 bool handled = false; |
| 367 | 367 |
| 368 // 1. Check out the element's tag name to decide how to deal with errors. | 368 // 1. Check out the element's tag name to decide how to deal with errors. |
| 369 if (n->isHTMLElement()) { | 369 if (n->isHTMLElement()) { |
| 370 HTMLElement* h = static_cast<HTMLElement*>(n); | 370 HTMLElement* h = static_cast<HTMLElement*>(n); |
| 371 if (h->hasLocalName(trTag) || h->hasLocalName(thTag) || h->hasLocalName(
tdTag)) { | 371 if (h->hasLocalName(trTag) || h->hasLocalName(thTag) || h->hasLocalName(
tdTag)) { |
| 372 if (inStrayTableContent && !isTableRelated(current)) { | 372 if (m_inStrayTableContent && !isTableRelated(m_current)) { |
| 373 reportError(MisplacedTablePartError, &localName, ¤t->local
Name()); | 373 reportError(MisplacedTablePartError, &localName, &m_current->loc
alName()); |
| 374 // pop out to the nearest enclosing table-related tag. | 374 // pop out to the nearest enclosing table-related tag. |
| 375 while (blockStack && !isTableRelated(current)) | 375 while (m_blockStack && !isTableRelated(m_current)) |
| 376 popOneBlock(); | 376 popOneBlock(); |
| 377 return insertNode(n); | 377 return insertNode(n); |
| 378 } | 378 } |
| 379 } else if (h->hasLocalName(headTag)) { | 379 } else if (h->hasLocalName(headTag)) { |
| 380 if (!current->isDocumentNode() && !current->hasTagName(htmlTag)) { | 380 if (!m_current->isDocumentNode() && !m_current->hasTagName(htmlTag))
{ |
| 381 reportError(MisplacedHeadError); | 381 reportError(MisplacedHeadError); |
| 382 return false; | 382 return false; |
| 383 } | 383 } |
| 384 } else if (h->hasLocalName(metaTag) || h->hasLocalName(linkTag) || h->ha
sLocalName(baseTag)) { | 384 } else if (h->hasLocalName(metaTag) || h->hasLocalName(linkTag) || h->ha
sLocalName(baseTag)) { |
| 385 bool createdHead = false; | 385 bool createdHead = false; |
| 386 if (!head) { | 386 if (!m_head) { |
| 387 createHead(); | 387 createHead(); |
| 388 createdHead = true; | 388 createdHead = true; |
| 389 } | 389 } |
| 390 if (head) { | 390 if (m_head) { |
| 391 if (!createdHead) | 391 if (!createdHead) |
| 392 reportError(MisplacedHeadContentError, &localName, ¤t-
>localName()); | 392 reportError(MisplacedHeadContentError, &localName, &m_curren
t->localName()); |
| 393 if (head->addChild(n)) { | 393 if (m_head->addChild(n)) { |
| 394 if (!n->attached() && !m_isParsingFragment) | 394 if (!n->attached() && !m_isParsingFragment) |
| 395 n->attach(); | 395 n->attach(); |
| 396 return true; | 396 return true; |
| 397 } else | 397 } else |
| 398 return false; | 398 return false; |
| 399 } | 399 } |
| 400 } else if (h->hasLocalName(htmlTag)) { | 400 } else if (h->hasLocalName(htmlTag)) { |
| 401 if (!current->isDocumentNode() ) { | 401 if (!m_current->isDocumentNode() ) { |
| 402 if (document->documentElement() && document->documentElement()->
hasTagName(htmlTag)) { | 402 if (m_document->documentElement() && m_document->documentElement
()->hasTagName(htmlTag)) { |
| 403 reportError(RedundantHTMLBodyError, &localName); | 403 reportError(RedundantHTMLBodyError, &localName); |
| 404 // we have another <HTML> element.... apply attributes to ex
isting one | 404 // we have another <HTML> element.... apply attributes to ex
isting one |
| 405 // make sure we don't overwrite already existing attributes | 405 // make sure we don't overwrite already existing attributes |
| 406 NamedAttrMap* map = static_cast<Element*>(n)->attributes(tru
e); | 406 NamedAttrMap* map = static_cast<Element*>(n)->attributes(tru
e); |
| 407 Element* existingHTML = static_cast<Element*>(document->docu
mentElement()); | 407 Element* existingHTML = static_cast<Element*>(m_document->do
cumentElement()); |
| 408 NamedAttrMap* bmap = existingHTML->attributes(false); | 408 NamedAttrMap* bmap = existingHTML->attributes(false); |
| 409 for (unsigned l = 0; map && l < map->length(); ++l) { | 409 for (unsigned l = 0; map && l < map->length(); ++l) { |
| 410 Attribute* it = map->attributeItem(l); | 410 Attribute* it = map->attributeItem(l); |
| 411 if (!bmap->getAttributeItem(it->name())) | 411 if (!bmap->getAttributeItem(it->name())) |
| 412 existingHTML->setAttribute(it->name(), it->value()); | 412 existingHTML->setAttribute(it->name(), it->value()); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 return false; | 415 return false; |
| 416 } | 416 } |
| 417 } else if (h->hasLocalName(titleTag) || h->hasLocalName(styleTag)) { | 417 } else if (h->hasLocalName(titleTag) || h->hasLocalName(styleTag)) { |
| 418 bool createdHead = false; | 418 bool createdHead = false; |
| 419 if (!head) { | 419 if (!m_head) { |
| 420 createHead(); | 420 createHead(); |
| 421 createdHead = true; | 421 createdHead = true; |
| 422 } | 422 } |
| 423 if (head) { | 423 if (m_head) { |
| 424 Node* newNode = head->addChild(n); | 424 Node* newNode = m_head->addChild(n); |
| 425 if (!newNode) { | 425 if (!newNode) { |
| 426 setSkipMode(h->tagQName()); | 426 setSkipMode(h->tagQName()); |
| 427 return false; | 427 return false; |
| 428 } | 428 } |
| 429 | 429 |
| 430 if (!createdHead) | 430 if (!createdHead) |
| 431 reportError(MisplacedHeadContentError, &localName, ¤t-
>localName()); | 431 reportError(MisplacedHeadContentError, &localName, &m_curren
t->localName()); |
| 432 | 432 |
| 433 pushBlock(localName, tagPriority); | 433 pushBlock(localName, tagPriority); |
| 434 newNode->beginParsingChildren(); | 434 newNode->beginParsingChildren(); |
| 435 setCurrent(newNode); | 435 setCurrent(newNode); |
| 436 if (!n->attached() && !m_isParsingFragment) | 436 if (!n->attached() && !m_isParsingFragment) |
| 437 n->attach(); | 437 n->attach(); |
| 438 return true; | 438 return true; |
| 439 } | 439 } |
| 440 if (inBody) { | 440 if (m_inBody) { |
| 441 setSkipMode(h->tagQName()); | 441 setSkipMode(h->tagQName()); |
| 442 return false; | 442 return false; |
| 443 } | 443 } |
| 444 } else if (h->hasLocalName(bodyTag)) { | 444 } else if (h->hasLocalName(bodyTag)) { |
| 445 if (inBody && document->body()) { | 445 if (m_inBody && m_document->body()) { |
| 446 // we have another <BODY> element.... apply attributes to existi
ng one | 446 // we have another <BODY> element.... apply attributes to existi
ng one |
| 447 // make sure we don't overwrite already existing attributes | 447 // make sure we don't overwrite already existing attributes |
| 448 // some sites use <body bgcolor=rightcolor>...<body bgcolor=wron
gcolor> | 448 // some sites use <body bgcolor=rightcolor>...<body bgcolor=wron
gcolor> |
| 449 reportError(RedundantHTMLBodyError, &localName); | 449 reportError(RedundantHTMLBodyError, &localName); |
| 450 NamedAttrMap* map = static_cast<Element*>(n)->attributes(true); | 450 NamedAttrMap* map = static_cast<Element*>(n)->attributes(true); |
| 451 Element* existingBody = document->body(); | 451 Element* existingBody = m_document->body(); |
| 452 NamedAttrMap* bmap = existingBody->attributes(false); | 452 NamedAttrMap* bmap = existingBody->attributes(false); |
| 453 for (unsigned l = 0; map && l < map->length(); ++l) { | 453 for (unsigned l = 0; map && l < map->length(); ++l) { |
| 454 Attribute* it = map->attributeItem(l); | 454 Attribute* it = map->attributeItem(l); |
| 455 if (!bmap->getAttributeItem(it->name())) | 455 if (!bmap->getAttributeItem(it->name())) |
| 456 existingBody->setAttribute(it->name(), it->value()); | 456 existingBody->setAttribute(it->name(), it->value()); |
| 457 } | 457 } |
| 458 return false; | 458 return false; |
| 459 } | 459 } |
| 460 else if (!current->isDocumentNode()) | 460 else if (!m_current->isDocumentNode()) |
| 461 return false; | 461 return false; |
| 462 } else if (h->hasLocalName(areaTag)) { | 462 } else if (h->hasLocalName(areaTag)) { |
| 463 if (m_currentMapElement) { | 463 if (m_currentMapElement) { |
| 464 reportError(MisplacedAreaError, ¤t->localName()); | 464 reportError(MisplacedAreaError, &m_current->localName()); |
| 465 m_currentMapElement->addChild(n); | 465 m_currentMapElement->addChild(n); |
| 466 if (!n->attached() && !m_isParsingFragment) | 466 if (!n->attached() && !m_isParsingFragment) |
| 467 n->attach(); | 467 n->attach(); |
| 468 handled = true; | 468 handled = true; |
| 469 return true; | 469 return true; |
| 470 } | 470 } |
| 471 return false; | 471 return false; |
| 472 } else if (h->hasLocalName(colgroupTag) || h->hasLocalName(captionTag))
{ | 472 } else if (h->hasLocalName(colgroupTag) || h->hasLocalName(captionTag))
{ |
| 473 if (isTableRelated(current)) { | 473 if (isTableRelated(m_current)) { |
| 474 while (blockStack && isTablePart(current)) | 474 while (m_blockStack && isTablePart(m_current)) |
| 475 popOneBlock(); | 475 popOneBlock(); |
| 476 return insertNode(n); | 476 return insertNode(n); |
| 477 } | 477 } |
| 478 } | 478 } |
| 479 } else if (n->isCommentNode() && !head) | 479 } else if (n->isCommentNode() && !m_head) |
| 480 return false; | 480 return false; |
| 481 | 481 |
| 482 // 2. Next we examine our currently active element to do some further error
handling. | 482 // 2. Next we examine our currently active element to do some further error
handling. |
| 483 if (current->isHTMLElement()) { | 483 if (m_current->isHTMLElement()) { |
| 484 HTMLElement* h = static_cast<HTMLElement*>(current); | 484 HTMLElement* h = static_cast<HTMLElement*>(m_current); |
| 485 const AtomicString& currentTagName = h->localName(); | 485 const AtomicString& currentTagName = h->localName(); |
| 486 if (h->hasLocalName(htmlTag)) { | 486 if (h->hasLocalName(htmlTag)) { |
| 487 HTMLElement* elt = n->isHTMLElement() ? static_cast<HTMLElement*>(n)
: 0; | 487 HTMLElement* elt = n->isHTMLElement() ? static_cast<HTMLElement*>(n)
: 0; |
| 488 if (elt && (elt->hasLocalName(scriptTag) || elt->hasLocalName(styleT
ag) || | 488 if (elt && (elt->hasLocalName(scriptTag) || elt->hasLocalName(styleT
ag) || |
| 489 elt->hasLocalName(metaTag) || elt->hasLocalName(linkTag) || | 489 elt->hasLocalName(metaTag) || elt->hasLocalName(linkTag) || |
| 490 elt->hasLocalName(objectTag) || elt->hasLocalName(embedTag) || | 490 elt->hasLocalName(objectTag) || elt->hasLocalName(embedTag) || |
| 491 elt->hasLocalName(titleTag) || elt->hasLocalName(isindexTag) || | 491 elt->hasLocalName(titleTag) || elt->hasLocalName(isindexTag) || |
| 492 elt->hasLocalName(baseTag))) { | 492 elt->hasLocalName(baseTag))) { |
| 493 if (!head) { | 493 if (!m_head) { |
| 494 head = new HTMLHeadElement(headTag, document); | 494 m_head = new HTMLHeadElement(headTag, m_document); |
| 495 e = head; | 495 e = m_head; |
| 496 insertNode(e); | 496 insertNode(e); |
| 497 handled = true; | 497 handled = true; |
| 498 } | 498 } |
| 499 } else { | 499 } else { |
| 500 if (n->isTextNode()) { | 500 if (n->isTextNode()) { |
| 501 Text* t = static_cast<Text*>(n); | 501 Text* t = static_cast<Text*>(n); |
| 502 if (t->containsOnlyWhitespace()) | 502 if (t->containsOnlyWhitespace()) |
| 503 return false; | 503 return false; |
| 504 } | 504 } |
| 505 if (!haveFrameSet) { | 505 if (!m_haveFrameSet) { |
| 506 e = new HTMLBodyElement(bodyTag, document); | 506 e = new HTMLBodyElement(bodyTag, m_document); |
| 507 startBody(); | 507 startBody(); |
| 508 insertNode(e); | 508 insertNode(e); |
| 509 handled = true; | 509 handled = true; |
| 510 } else | 510 } else |
| 511 reportError(MisplacedFramesetContentError, &localName); | 511 reportError(MisplacedFramesetContentError, &localName); |
| 512 } | 512 } |
| 513 } else if (h->hasLocalName(headTag)) { | 513 } else if (h->hasLocalName(headTag)) { |
| 514 if (n->hasTagName(htmlTag)) | 514 if (n->hasTagName(htmlTag)) |
| 515 return false; | 515 return false; |
| 516 else { | 516 else { |
| 517 // This means the body starts here... | 517 // This means the body starts here... |
| 518 if (!haveFrameSet) { | 518 if (!m_haveFrameSet) { |
| 519 popBlock(currentTagName); | 519 popBlock(currentTagName); |
| 520 e = new HTMLBodyElement(bodyTag, document); | 520 e = new HTMLBodyElement(bodyTag, m_document); |
| 521 startBody(); | 521 startBody(); |
| 522 insertNode(e); | 522 insertNode(e); |
| 523 handled = true; | 523 handled = true; |
| 524 } else | 524 } else |
| 525 reportError(MisplacedFramesetContentError, &localName); | 525 reportError(MisplacedFramesetContentError, &localName); |
| 526 } | 526 } |
| 527 } else if (h->hasLocalName(addressTag) || h->hasLocalName(fontTag) | 527 } else if (h->hasLocalName(addressTag) || h->hasLocalName(fontTag) |
| 528 || h->hasLocalName(styleTag) || h->hasLocalName(titleTag)) { | 528 || h->hasLocalName(styleTag) || h->hasLocalName(titleTag)) { |
| 529 reportError(MisplacedContentRetryError, &localName, ¤tTagName)
; | 529 reportError(MisplacedContentRetryError, &localName, ¤tTagName)
; |
| 530 popBlock(currentTagName); | 530 popBlock(currentTagName); |
| 531 handled = true; | 531 handled = true; |
| 532 } else if (h->hasLocalName(captionTag)) { | 532 } else if (h->hasLocalName(captionTag)) { |
| 533 // Illegal content in a caption. Close the caption and try again. | 533 // Illegal content in a caption. Close the caption and try again. |
| 534 reportError(MisplacedCaptionContentError, &localName); | 534 reportError(MisplacedCaptionContentError, &localName); |
| 535 popBlock(currentTagName); | 535 popBlock(currentTagName); |
| 536 if (isTablePart(n)) | 536 if (isTablePart(n)) |
| 537 return insertNode(n, flat); | 537 return insertNode(n, flat); |
| 538 } else if (h->hasLocalName(tableTag) || h->hasLocalName(trTag) || isTabl
eSection(h)) { | 538 } else if (h->hasLocalName(tableTag) || h->hasLocalName(trTag) || isTabl
eSection(h)) { |
| 539 if (n->hasTagName(tableTag)) { | 539 if (n->hasTagName(tableTag)) { |
| 540 reportError(MisplacedTableError, ¤tTagName); | 540 reportError(MisplacedTableError, ¤tTagName); |
| 541 if (m_isParsingFragment && !h->hasLocalName(tableTag)) | 541 if (m_isParsingFragment && !h->hasLocalName(tableTag)) |
| 542 // fragment may contain table parts without <table> ancestor
, pop them one by one | 542 // fragment may contain table parts without <table> ancestor
, pop them one by one |
| 543 popBlock(h->localName()); | 543 popBlock(h->localName()); |
| 544 popBlock(localName); // end the table | 544 popBlock(localName); // end the table |
| 545 handled = true; // ...and start a new one | 545 handled = true; // ...and start a new one |
| 546 } else { | 546 } else { |
| 547 ExceptionCode ec = 0; | 547 ExceptionCode ec = 0; |
| 548 Node* node = current; | 548 Node* node = m_current; |
| 549 Node* parent = node->parentNode(); | 549 Node* parent = node->parentNode(); |
| 550 // A script may have removed the current node's parent from the
DOM | 550 // A script may have removed the current node's parent from the
DOM |
| 551 // http://bugs.webkit.org/show_bug.cgi?id=7137 | 551 // http://bugs.webkit.org/show_bug.cgi?id=7137 |
| 552 // FIXME: we should do real recovery here and re-parent with the
correct node. | 552 // FIXME: we should do real recovery here and re-parent with the
correct node. |
| 553 if (!parent) | 553 if (!parent) |
| 554 return false; | 554 return false; |
| 555 Node* grandparent = parent->parentNode(); | 555 Node* grandparent = parent->parentNode(); |
| 556 | 556 |
| 557 if (n->isTextNode() || | 557 if (n->isTextNode() || |
| 558 (h->hasLocalName(trTag) && | 558 (h->hasLocalName(trTag) && |
| (...skipping 11 matching lines...) Expand all Loading... |
| 570 return false; | 570 return false; |
| 571 parent->insertBefore(n, node, ec); | 571 parent->insertBefore(n, node, ec); |
| 572 if (!ec) { | 572 if (!ec) { |
| 573 reportError(StrayTableContentError, &localName, ¤t
TagName); | 573 reportError(StrayTableContentError, &localName, ¤t
TagName); |
| 574 if (n->isHTMLElement() && tagPriority > 0 && | 574 if (n->isHTMLElement() && tagPriority > 0 && |
| 575 !flat && static_cast<HTMLElement*>(n)->endTagRequire
ment() != TagStatusForbidden) | 575 !flat && static_cast<HTMLElement*>(n)->endTagRequire
ment() != TagStatusForbidden) |
| 576 { | 576 { |
| 577 pushBlock(localName, tagPriority); | 577 pushBlock(localName, tagPriority); |
| 578 n->beginParsingChildren(); | 578 n->beginParsingChildren(); |
| 579 setCurrent(n); | 579 setCurrent(n); |
| 580 inStrayTableContent++; | 580 m_inStrayTableContent++; |
| 581 blockStack->strayTableContent = true; | 581 m_blockStack->strayTableContent = true; |
| 582 } | 582 } |
| 583 return true; | 583 return true; |
| 584 } | 584 } |
| 585 } | 585 } |
| 586 | 586 |
| 587 if (!ec) { | 587 if (!ec) { |
| 588 if (current->hasTagName(trTag)) { | 588 if (m_current->hasTagName(trTag)) { |
| 589 reportError(TablePartRequiredError, &localName, &tdTag.l
ocalName()); | 589 reportError(TablePartRequiredError, &localName, &tdTag.l
ocalName()); |
| 590 e = new HTMLTableCellElement(tdTag, document); | 590 e = new HTMLTableCellElement(tdTag, m_document); |
| 591 } else if (current->hasTagName(tableTag)) { | 591 } else if (m_current->hasTagName(tableTag)) { |
| 592 // Don't report an error in this case, since making a <t
body> happens all the time when you have <table><tr>, | 592 // Don't report an error in this case, since making a <t
body> happens all the time when you have <table><tr>, |
| 593 // and it isn't really a parse error per se. | 593 // and it isn't really a parse error per se. |
| 594 e = new HTMLTableSectionElement(tbodyTag, document); | 594 e = new HTMLTableSectionElement(tbodyTag, m_document); |
| 595 } else { | 595 } else { |
| 596 reportError(TablePartRequiredError, &localName, &trTag.l
ocalName()); | 596 reportError(TablePartRequiredError, &localName, &trTag.l
ocalName()); |
| 597 e = new HTMLTableRowElement(trTag, document); | 597 e = new HTMLTableRowElement(trTag, m_document); |
| 598 } | 598 } |
| 599 | 599 |
| 600 insertNode(e); | 600 insertNode(e); |
| 601 handled = true; | 601 handled = true; |
| 602 } | 602 } |
| 603 } | 603 } |
| 604 } else if (h->hasLocalName(objectTag)) { | 604 } else if (h->hasLocalName(objectTag)) { |
| 605 reportError(MisplacedContentRetryError, &localName, ¤tTagName)
; | 605 reportError(MisplacedContentRetryError, &localName, ¤tTagName)
; |
| 606 popBlock(objectTag); | 606 popBlock(objectTag); |
| 607 handled = true; | 607 handled = true; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 621 } else if (h->hasLocalName(selectTag)) { | 621 } else if (h->hasLocalName(selectTag)) { |
| 622 if (localName == inputTag || localName == textareaTag) { | 622 if (localName == inputTag || localName == textareaTag) { |
| 623 reportError(MisplacedContentRetryError, &localName, ¤tTagN
ame); | 623 reportError(MisplacedContentRetryError, &localName, ¤tTagN
ame); |
| 624 popBlock(currentTagName); | 624 popBlock(currentTagName); |
| 625 handled = true; | 625 handled = true; |
| 626 } | 626 } |
| 627 } else if (h->hasLocalName(colgroupTag)) { | 627 } else if (h->hasLocalName(colgroupTag)) { |
| 628 popBlock(currentTagName); | 628 popBlock(currentTagName); |
| 629 handled = true; | 629 handled = true; |
| 630 } else if (!h->hasLocalName(bodyTag)) { | 630 } else if (!h->hasLocalName(bodyTag)) { |
| 631 if (isInline(current)) { | 631 if (isInline(m_current)) { |
| 632 popInlineBlocks(); | 632 popInlineBlocks(); |
| 633 handled = true; | 633 handled = true; |
| 634 } | 634 } |
| 635 } | 635 } |
| 636 } else if (current->isDocumentNode()) { | 636 } else if (m_current->isDocumentNode()) { |
| 637 if (n->isTextNode()) { | 637 if (n->isTextNode()) { |
| 638 Text* t = static_cast<Text*>(n); | 638 Text* t = static_cast<Text*>(n); |
| 639 if (t->containsOnlyWhitespace()) | 639 if (t->containsOnlyWhitespace()) |
| 640 return false; | 640 return false; |
| 641 } | 641 } |
| 642 | 642 |
| 643 if (!document->documentElement()) { | 643 if (!m_document->documentElement()) { |
| 644 e = new HTMLHtmlElement(htmlTag, document); | 644 e = new HTMLHtmlElement(htmlTag, m_document); |
| 645 insertNode(e); | 645 insertNode(e); |
| 646 handled = true; | 646 handled = true; |
| 647 } | 647 } |
| 648 } | 648 } |
| 649 | 649 |
| 650 // 3. If we couldn't handle the error, just return false and attempt to erro
r-correct again. | 650 // 3. If we couldn't handle the error, just return false and attempt to erro
r-correct again. |
| 651 if (!handled) { | 651 if (!handled) { |
| 652 reportError(IgnoredContentError, &localName, ¤t->localName()); | 652 reportError(IgnoredContentError, &localName, &m_current->localName()); |
| 653 return false; | 653 return false; |
| 654 } | 654 } |
| 655 return insertNode(n); | 655 return insertNode(n); |
| 656 } | 656 } |
| 657 | 657 |
| 658 typedef bool (HTMLParser::*CreateErrorCheckFunc)(Token* t, RefPtr<Node>&); | 658 typedef bool (HTMLParser::*CreateErrorCheckFunc)(Token* t, RefPtr<Node>&); |
| 659 typedef HashMap<AtomicStringImpl*, CreateErrorCheckFunc> FunctionMap; | 659 typedef HashMap<AtomicStringImpl*, CreateErrorCheckFunc> FunctionMap; |
| 660 | 660 |
| 661 bool HTMLParser::textCreateErrorCheck(Token* t, RefPtr<Node>& result) | 661 bool HTMLParser::textCreateErrorCheck(Token* t, RefPtr<Node>& result) |
| 662 { | 662 { |
| 663 result = new Text(document, t->text.get()); | 663 result = new Text(m_document, t->text.get()); |
| 664 return false; | 664 return false; |
| 665 } | 665 } |
| 666 | 666 |
| 667 bool HTMLParser::commentCreateErrorCheck(Token* t, RefPtr<Node>& result) | 667 bool HTMLParser::commentCreateErrorCheck(Token* t, RefPtr<Node>& result) |
| 668 { | 668 { |
| 669 result = new Comment(document, t->text.get()); | 669 result = new Comment(m_document, t->text.get()); |
| 670 return false; | 670 return false; |
| 671 } | 671 } |
| 672 | 672 |
| 673 bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result) | 673 bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result) |
| 674 { | 674 { |
| 675 if (!head || current->localName() == htmlTag) { | 675 if (!m_head || m_current->localName() == htmlTag) { |
| 676 head = new HTMLHeadElement(headTag, document); | 676 m_head = new HTMLHeadElement(headTag, m_document); |
| 677 result = head; | 677 result = m_head; |
| 678 } else | 678 } else |
| 679 reportError(MisplacedHeadError); | 679 reportError(MisplacedHeadError); |
| 680 return false; | 680 return false; |
| 681 } | 681 } |
| 682 | 682 |
| 683 bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&) | 683 bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&) |
| 684 { | 684 { |
| 685 // body no longer allowed if we have a frameset | 685 // body no longer allowed if we have a frameset |
| 686 if (haveFrameSet) | 686 if (m_haveFrameSet) |
| 687 return false; | 687 return false; |
| 688 popBlock(headTag); | 688 popBlock(headTag); |
| 689 startBody(); | 689 startBody(); |
| 690 return true; | 690 return true; |
| 691 } | 691 } |
| 692 | 692 |
| 693 bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&) | 693 bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&) |
| 694 { | 694 { |
| 695 popBlock(headTag); | 695 popBlock(headTag); |
| 696 if (inBody && !haveFrameSet && !haveContent) { | 696 if (m_inBody && !m_haveFrameSet && !m_haveContent) { |
| 697 popBlock(bodyTag); | 697 popBlock(bodyTag); |
| 698 // ### actually for IE document.body returns the now hidden "body" eleme
nt | 698 // ### actually for IE document.body returns the now hidden "body" eleme
nt |
| 699 // we can't implement that behaviour now because it could cause too many | 699 // we can't implement that behaviour now because it could cause too many |
| 700 // regressions and the headaches are not worth the work as long as there
is | 700 // regressions and the headaches are not worth the work as long as there
is |
| 701 // no site actually relying on that detail (Dirk) | 701 // no site actually relying on that detail (Dirk) |
| 702 if (document->body()) | 702 if (m_document->body()) |
| 703 document->body()->setAttribute(styleAttr, "display:none"); | 703 m_document->body()->setAttribute(styleAttr, "display:none"); |
| 704 inBody = false; | 704 m_inBody = false; |
| 705 } | 705 } |
| 706 if ((haveContent || haveFrameSet) && current->localName() == htmlTag) | 706 if ((m_haveContent || m_haveFrameSet) && m_current->localName() == htmlTag) |
| 707 return false; | 707 return false; |
| 708 haveFrameSet = true; | 708 m_haveFrameSet = true; |
| 709 startBody(); | 709 startBody(); |
| 710 return true; | 710 return true; |
| 711 } | 711 } |
| 712 | 712 |
| 713 bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result) | 713 bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result) |
| 714 { | 714 { |
| 715 // Only create a new form if we're not already inside one. | 715 // Only create a new form if we're not already inside one. |
| 716 // This is consistent with other browsers' behavior. | 716 // This is consistent with other browsers' behavior. |
| 717 if (!m_currentFormElement) { | 717 if (!m_currentFormElement) { |
| 718 m_currentFormElement = new HTMLFormElement(formTag, document); | 718 m_currentFormElement = new HTMLFormElement(formTag, m_document); |
| 719 result = m_currentFormElement; | 719 result = m_currentFormElement; |
| 720 pCloserCreateErrorCheck(t, result); | 720 pCloserCreateErrorCheck(t, result); |
| 721 } | 721 } |
| 722 return false; | 722 return false; |
| 723 } | 723 } |
| 724 | 724 |
| 725 bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result) | 725 bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result) |
| 726 { | 726 { |
| 727 RefPtr<Node> n = handleIsindex(t); | 727 RefPtr<Node> n = handleIsindex(t); |
| 728 if (!inBody) | 728 if (!m_inBody) |
| 729 m_isindexElement = n.release(); | 729 m_isindexElement = n.release(); |
| 730 else { | 730 else { |
| 731 t->selfClosingTag = true; | 731 t->selfClosingTag = true; |
| 732 result = n.release(); | 732 result = n.release(); |
| 733 } | 733 } |
| 734 return false; | 734 return false; |
| 735 } | 735 } |
| 736 | 736 |
| 737 bool HTMLParser::selectCreateErrorCheck(Token*, RefPtr<Node>&) | 737 bool HTMLParser::selectCreateErrorCheck(Token*, RefPtr<Node>&) |
| 738 { | 738 { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 | 796 |
| 797 bool HTMLParser::noframesCreateErrorCheck(Token*, RefPtr<Node>&) | 797 bool HTMLParser::noframesCreateErrorCheck(Token*, RefPtr<Node>&) |
| 798 { | 798 { |
| 799 setSkipMode(noframesTag); | 799 setSkipMode(noframesTag); |
| 800 return true; | 800 return true; |
| 801 } | 801 } |
| 802 | 802 |
| 803 bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&) | 803 bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&) |
| 804 { | 804 { |
| 805 if (!m_isParsingFragment) { | 805 if (!m_isParsingFragment) { |
| 806 Settings* settings = document->settings(); | 806 Settings* settings = m_document->settings(); |
| 807 if (settings && settings->isJavaScriptEnabled()) | 807 if (settings && settings->isJavaScriptEnabled()) |
| 808 setSkipMode(noscriptTag); | 808 setSkipMode(noscriptTag); |
| 809 } | 809 } |
| 810 return true; | 810 return true; |
| 811 } | 811 } |
| 812 | 812 |
| 813 bool HTMLParser::pCloserCreateErrorCheck(Token*, RefPtr<Node>&) | 813 bool HTMLParser::pCloserCreateErrorCheck(Token*, RefPtr<Node>&) |
| 814 { | 814 { |
| 815 if (hasPElementInScope()) | 815 if (hasPElementInScope()) |
| 816 popBlock(pTag); | 816 popBlock(pTag); |
| 817 return true; | 817 return true; |
| 818 } | 818 } |
| 819 | 819 |
| 820 bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&) | 820 bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&) |
| 821 { | 821 { |
| 822 if (document->inCompatMode()) | 822 if (m_document->inCompatMode()) |
| 823 return true; | 823 return true; |
| 824 if (hasPElementInScope()) | 824 if (hasPElementInScope()) |
| 825 popBlock(pTag); | 825 popBlock(pTag); |
| 826 return true; | 826 return true; |
| 827 } | 827 } |
| 828 | 828 |
| 829 bool HTMLParser::mapCreateErrorCheck(Token*, RefPtr<Node>& result) | 829 bool HTMLParser::mapCreateErrorCheck(Token*, RefPtr<Node>& result) |
| 830 { | 830 { |
| 831 m_currentMapElement = new HTMLMapElement(mapTag, document); | 831 m_currentMapElement = new HTMLMapElement(mapTag, m_document); |
| 832 result = m_currentMapElement; | 832 result = m_currentMapElement; |
| 833 return false; | 833 return false; |
| 834 } | 834 } |
| 835 | 835 |
| 836 PassRefPtr<Node> HTMLParser::getNode(Token* t) | 836 PassRefPtr<Node> HTMLParser::getNode(Token* t) |
| 837 { | 837 { |
| 838 // Init our error handling table. | 838 // Init our error handling table. |
| 839 DEFINE_STATIC_LOCAL(FunctionMap, gFunctionMap, ()); | 839 DEFINE_STATIC_LOCAL(FunctionMap, gFunctionMap, ()); |
| 840 if (gFunctionMap.isEmpty()) { | 840 if (gFunctionMap.isEmpty()) { |
| 841 gFunctionMap.set(aTag.localName().impl(), &HTMLParser::nestedCreateError
Check); | 841 gFunctionMap.set(aTag.localName().impl(), &HTMLParser::nestedCreateError
Check); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 gFunctionMap.set(ttTag.localName().impl(), &HTMLParser::nestedStyleCreat
eErrorCheck); | 892 gFunctionMap.set(ttTag.localName().impl(), &HTMLParser::nestedStyleCreat
eErrorCheck); |
| 893 gFunctionMap.set(uTag.localName().impl(), &HTMLParser::nestedStyleCreate
ErrorCheck); | 893 gFunctionMap.set(uTag.localName().impl(), &HTMLParser::nestedStyleCreate
ErrorCheck); |
| 894 gFunctionMap.set(ulTag.localName().impl(), &HTMLParser::pCloserCreateErr
orCheck); | 894 gFunctionMap.set(ulTag.localName().impl(), &HTMLParser::pCloserCreateErr
orCheck); |
| 895 } | 895 } |
| 896 | 896 |
| 897 bool proceed = true; | 897 bool proceed = true; |
| 898 RefPtr<Node> result; | 898 RefPtr<Node> result; |
| 899 if (CreateErrorCheckFunc errorCheckFunc = gFunctionMap.get(t->tagName.impl()
)) | 899 if (CreateErrorCheckFunc errorCheckFunc = gFunctionMap.get(t->tagName.impl()
)) |
| 900 proceed = (this->*errorCheckFunc)(t, result); | 900 proceed = (this->*errorCheckFunc)(t, result); |
| 901 if (proceed) | 901 if (proceed) |
| 902 result = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, t
->tagName, xhtmlNamespaceURI), document, m_currentFormElement.get()); | 902 result = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, t
->tagName, xhtmlNamespaceURI), m_document, m_currentFormElement.get()); |
| 903 return result.release(); | 903 return result.release(); |
| 904 } | 904 } |
| 905 | 905 |
| 906 bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName) | 906 bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName) |
| 907 { | 907 { |
| 908 // www.liceo.edu.mx is an example of a site that achieves a level of nesting
of | 908 // www.liceo.edu.mx is an example of a site that achieves a level of nesting
of |
| 909 // about 1500 tags, all from a bunch of <b>s. We will only allow at most 20 | 909 // about 1500 tags, all from a bunch of <b>s. We will only allow at most 20 |
| 910 // nested tags of the same type before just ignoring them all together. | 910 // nested tags of the same type before just ignoring them all together. |
| 911 unsigned i = 0; | 911 unsigned i = 0; |
| 912 for (HTMLStackElem* curr = blockStack; | 912 for (HTMLStackElem* curr = m_blockStack; |
| 913 i < cMaxRedundantTagDepth && curr && curr->tagName == tagName; | 913 i < cMaxRedundantTagDepth && curr && curr->tagName == tagName; |
| 914 curr = curr->next, i++) { } | 914 curr = curr->next, i++) { } |
| 915 return i != cMaxRedundantTagDepth; | 915 return i != cMaxRedundantTagDepth; |
| 916 } | 916 } |
| 917 | 917 |
| 918 void HTMLParser::processCloseTag(Token* t) | 918 void HTMLParser::processCloseTag(Token* t) |
| 919 { | 919 { |
| 920 // Support for really broken html. | 920 // Support for really broken html. |
| 921 // we never close the body tag, since some stupid web pages close it before
the actual end of the doc. | 921 // we never close the body tag, since some stupid web pages close it before
the actual end of the doc. |
| 922 // let's rely on the end() call to close things. | 922 // let's rely on the end() call to close things. |
| 923 if (t->tagName == htmlTag || t->tagName == bodyTag || t->tagName == commentA
tom) | 923 if (t->tagName == htmlTag || t->tagName == bodyTag || t->tagName == commentA
tom) |
| 924 return; | 924 return; |
| 925 | 925 |
| 926 bool checkForCloseTagErrors = true; | 926 bool checkForCloseTagErrors = true; |
| 927 if (t->tagName == formTag && m_currentFormElement) { | 927 if (t->tagName == formTag && m_currentFormElement) { |
| 928 m_currentFormElement = 0; | 928 m_currentFormElement = 0; |
| 929 checkForCloseTagErrors = false; | 929 checkForCloseTagErrors = false; |
| 930 } else if (t->tagName == mapTag) | 930 } else if (t->tagName == mapTag) |
| 931 m_currentMapElement = 0; | 931 m_currentMapElement = 0; |
| 932 else if (t->tagName == pTag) | 932 else if (t->tagName == pTag) |
| 933 checkForCloseTagErrors = false; | 933 checkForCloseTagErrors = false; |
| 934 | 934 |
| 935 HTMLStackElem* oldElem = blockStack; | 935 HTMLStackElem* oldElem = m_blockStack; |
| 936 popBlock(t->tagName, checkForCloseTagErrors); | 936 popBlock(t->tagName, checkForCloseTagErrors); |
| 937 if (oldElem == blockStack && t->tagName == pTag) { | 937 if (oldElem == m_blockStack && t->tagName == pTag) { |
| 938 // We encountered a stray </p>. Amazingly Gecko, WinIE, and MacIE all t
reat | 938 // We encountered a stray </p>. Amazingly Gecko, WinIE, and MacIE all t
reat |
| 939 // this as a valid break, i.e., <p></p>. So go ahead and make the empty | 939 // this as a valid break, i.e., <p></p>. So go ahead and make the empty |
| 940 // paragraph. | 940 // paragraph. |
| 941 t->beginTag = true; | 941 t->beginTag = true; |
| 942 parseToken(t); | 942 parseToken(t); |
| 943 popBlock(t->tagName); | 943 popBlock(t->tagName); |
| 944 reportError(StrayParagraphCloseError); | 944 reportError(StrayParagraphCloseError); |
| 945 } | 945 } |
| 946 } | 946 } |
| 947 | 947 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 972 e->hasLocalName(sTag) || e->hasLocalName(strikeTag) || e->hasLocalNa
me(bigTag) || | 972 e->hasLocalName(sTag) || e->hasLocalName(strikeTag) || e->hasLocalNa
me(bigTag) || |
| 973 e->hasLocalName(smallTag) || e->hasLocalName(emTag) || e->hasLocalNa
me(strongTag) || | 973 e->hasLocalName(smallTag) || e->hasLocalName(emTag) || e->hasLocalNa
me(strongTag) || |
| 974 e->hasLocalName(dfnTag) || e->hasLocalName(codeTag) || e->hasLocalNa
me(sampTag) || | 974 e->hasLocalName(dfnTag) || e->hasLocalName(codeTag) || e->hasLocalNa
me(sampTag) || |
| 975 e->hasLocalName(kbdTag) || e->hasLocalName(varTag) || e->hasLocalNam
e(citeTag) || | 975 e->hasLocalName(kbdTag) || e->hasLocalName(varTag) || e->hasLocalNam
e(citeTag) || |
| 976 e->hasLocalName(abbrTag) || e->hasLocalName(acronymTag) || e->hasLoc
alName(subTag) || | 976 e->hasLocalName(abbrTag) || e->hasLocalName(acronymTag) || e->hasLoc
alName(subTag) || |
| 977 e->hasLocalName(supTag) || e->hasLocalName(spanTag) || e->hasLocalNa
me(nobrTag) || | 977 e->hasLocalName(supTag) || e->hasLocalName(spanTag) || e->hasLocalNa
me(nobrTag) || |
| 978 e->hasLocalName(noframesTag) || e->hasLocalName(nolayerTag) || | 978 e->hasLocalName(noframesTag) || e->hasLocalName(nolayerTag) || |
| 979 e->hasLocalName(noembedTag)) | 979 e->hasLocalName(noembedTag)) |
| 980 return true; | 980 return true; |
| 981 if (e->hasLocalName(noscriptTag) && !m_isParsingFragment) { | 981 if (e->hasLocalName(noscriptTag) && !m_isParsingFragment) { |
| 982 Settings* settings = document->settings(); | 982 Settings* settings = m_document->settings(); |
| 983 if (settings && settings->isJavaScriptEnabled()) | 983 if (settings && settings->isJavaScriptEnabled()) |
| 984 return true; | 984 return true; |
| 985 } | 985 } |
| 986 } | 986 } |
| 987 | 987 |
| 988 return false; | 988 return false; |
| 989 } | 989 } |
| 990 | 990 |
| 991 bool HTMLParser::isResidualStyleTag(const AtomicString& tagName) | 991 bool HTMLParser::isResidualStyleTag(const AtomicString& tagName) |
| 992 { | 992 { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 { | 1043 { |
| 1044 HTMLStackElem* maxElem = 0; | 1044 HTMLStackElem* maxElem = 0; |
| 1045 bool finished = false; | 1045 bool finished = false; |
| 1046 bool strayTableContent = elem->strayTableContent; | 1046 bool strayTableContent = elem->strayTableContent; |
| 1047 | 1047 |
| 1048 m_handlingResidualStyleAcrossBlocks = true; | 1048 m_handlingResidualStyleAcrossBlocks = true; |
| 1049 while (!finished) { | 1049 while (!finished) { |
| 1050 // Find the outermost element that crosses over to a higher level. If th
ere exists another higher-level | 1050 // Find the outermost element that crosses over to a higher level. If th
ere exists another higher-level |
| 1051 // element, we will do another pass, until we have corrected the innermo
st one. | 1051 // element, we will do another pass, until we have corrected the innermo
st one. |
| 1052 ExceptionCode ec = 0; | 1052 ExceptionCode ec = 0; |
| 1053 HTMLStackElem* curr = blockStack; | 1053 HTMLStackElem* curr = m_blockStack; |
| 1054 HTMLStackElem* prev = 0; | 1054 HTMLStackElem* prev = 0; |
| 1055 HTMLStackElem* prevMaxElem = 0; | 1055 HTMLStackElem* prevMaxElem = 0; |
| 1056 maxElem = 0; | 1056 maxElem = 0; |
| 1057 finished = true; | 1057 finished = true; |
| 1058 while (curr && curr != elem) { | 1058 while (curr && curr != elem) { |
| 1059 if (curr->level > elem->level) { | 1059 if (curr->level > elem->level) { |
| 1060 if (!isAffectedByResidualStyle(curr->tagName)) | 1060 if (!isAffectedByResidualStyle(curr->tagName)) |
| 1061 return; | 1061 return; |
| 1062 if (maxElem) | 1062 if (maxElem) |
| 1063 // We will need another pass. | 1063 // We will need another pass. |
| 1064 finished = false; | 1064 finished = false; |
| 1065 maxElem = curr; | 1065 maxElem = curr; |
| 1066 prevMaxElem = prev; | 1066 prevMaxElem = prev; |
| 1067 } | 1067 } |
| 1068 | 1068 |
| 1069 prev = curr; | 1069 prev = curr; |
| 1070 curr = curr->next; | 1070 curr = curr->next; |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 if (!curr || !maxElem) | 1073 if (!curr || !maxElem) |
| 1074 return; | 1074 return; |
| 1075 | 1075 |
| 1076 Node* residualElem = prev->node; | 1076 Node* residualElem = prev->node; |
| 1077 Node* blockElem = prevMaxElem ? prevMaxElem->node : current; | 1077 Node* blockElem = prevMaxElem ? prevMaxElem->node : m_current; |
| 1078 Node* parentElem = elem->node; | 1078 Node* parentElem = elem->node; |
| 1079 | 1079 |
| 1080 // Check to see if the reparenting that is going to occur is allowed acc
ording to the DOM. | 1080 // Check to see if the reparenting that is going to occur is allowed acc
ording to the DOM. |
| 1081 // FIXME: We should either always allow it or perform an additional fixu
p instead of | 1081 // FIXME: We should either always allow it or perform an additional fixu
p instead of |
| 1082 // just bailing here. | 1082 // just bailing here. |
| 1083 // Example: <p><font><center>blah</font></center></p> isn't doing a fixu
p right now. | 1083 // Example: <p><font><center>blah</font></center></p> isn't doing a fixu
p right now. |
| 1084 if (!parentElem->childAllowed(blockElem)) | 1084 if (!parentElem->childAllowed(blockElem)) |
| 1085 return; | 1085 return; |
| 1086 | 1086 |
| 1087 m_hasPElementInScope = Unknown; | 1087 m_hasPElementInScope = Unknown; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 prevMaxElem->node = newNodePtr; | 1216 prevMaxElem->node = newNodePtr; |
| 1217 prevMaxElem->didRefNode = false; | 1217 prevMaxElem->didRefNode = false; |
| 1218 } else | 1218 } else |
| 1219 delete elem; | 1219 delete elem; |
| 1220 } | 1220 } |
| 1221 | 1221 |
| 1222 // FIXME: If we ever make a case like this work: | 1222 // FIXME: If we ever make a case like this work: |
| 1223 // <table><b><i><form></b></form></i></table> | 1223 // <table><b><i><form></b></form></i></table> |
| 1224 // Then this check will be too simplistic. Right now the <i><form> chain wi
ll end up inside the <tbody>, which is pretty crazy. | 1224 // Then this check will be too simplistic. Right now the <i><form> chain wi
ll end up inside the <tbody>, which is pretty crazy. |
| 1225 if (strayTableContent) | 1225 if (strayTableContent) |
| 1226 inStrayTableContent--; | 1226 m_inStrayTableContent--; |
| 1227 | 1227 |
| 1228 // Step 7: Reopen intermediate inlines, e.g., <b><p><i>Foo</b>Goo</p>. | 1228 // Step 7: Reopen intermediate inlines, e.g., <b><p><i>Foo</b>Goo</p>. |
| 1229 // In the above example, Goo should stay italic. | 1229 // In the above example, Goo should stay italic. |
| 1230 // We cap the number of tags we're willing to reopen based off cResidualStyl
eMaxDepth. | 1230 // We cap the number of tags we're willing to reopen based off cResidualStyl
eMaxDepth. |
| 1231 | 1231 |
| 1232 HTMLStackElem* curr = blockStack; | 1232 HTMLStackElem* curr = m_blockStack; |
| 1233 HTMLStackElem* residualStyleStack = 0; | 1233 HTMLStackElem* residualStyleStack = 0; |
| 1234 unsigned stackDepth = 1; | 1234 unsigned stackDepth = 1; |
| 1235 unsigned redundantStyleCount = 0; | 1235 unsigned redundantStyleCount = 0; |
| 1236 while (curr && curr != maxElem) { | 1236 while (curr && curr != maxElem) { |
| 1237 // We will actually schedule this tag for reopening | 1237 // We will actually schedule this tag for reopening |
| 1238 // after we complete the close of this entire block. | 1238 // after we complete the close of this entire block. |
| 1239 if (isResidualStyleTag(curr->tagName) && stackDepth++ < cResidualStyleMa
xDepth) { | 1239 if (isResidualStyleTag(curr->tagName) && stackDepth++ < cResidualStyleMa
xDepth) { |
| 1240 // We've overloaded the use of stack elements and are just reusing t
he | 1240 // We've overloaded the use of stack elements and are just reusing t
he |
| 1241 // struct with a slightly different meaning to the variables. Inste
ad of chaining | 1241 // struct with a slightly different meaning to the variables. Inste
ad of chaining |
| 1242 // from innermost to outermost, we build up a list of all the tags w
e need to reopen | 1242 // from innermost to outermost, we build up a list of all the tags w
e need to reopen |
| 1243 // from the outermost to the innermost, i.e., residualStyleStack wil
l end up pointing | 1243 // from the outermost to the innermost, i.e., residualStyleStack wil
l end up pointing |
| 1244 // to the outermost tag we need to reopen. | 1244 // to the outermost tag we need to reopen. |
| 1245 // We also set curr->node to be the actual element that corresponds
to the ID stored in | 1245 // We also set curr->node to be the actual element that corresponds
to the ID stored in |
| 1246 // curr->id rather than the node that you should pop to when the ele
ment gets pulled off | 1246 // curr->id rather than the node that you should pop to when the ele
ment gets pulled off |
| 1247 // the stack. | 1247 // the stack. |
| 1248 if (residualStyleStack && curr->tagName == residualStyleStack->tagNa
me && curr->node->attributes()->mapsEquivalent(residualStyleStack->node->attribu
tes())) | 1248 if (residualStyleStack && curr->tagName == residualStyleStack->tagNa
me && curr->node->attributes()->mapsEquivalent(residualStyleStack->node->attribu
tes())) |
| 1249 redundantStyleCount++; | 1249 redundantStyleCount++; |
| 1250 else | 1250 else |
| 1251 redundantStyleCount = 0; | 1251 redundantStyleCount = 0; |
| 1252 | 1252 |
| 1253 if (redundantStyleCount < cMaxRedundantTagDepth) | 1253 if (redundantStyleCount < cMaxRedundantTagDepth) |
| 1254 moveOneBlockToStack(residualStyleStack); | 1254 moveOneBlockToStack(residualStyleStack); |
| 1255 else | 1255 else |
| 1256 popOneBlock(); | 1256 popOneBlock(); |
| 1257 } else | 1257 } else |
| 1258 popOneBlock(); | 1258 popOneBlock(); |
| 1259 | 1259 |
| 1260 curr = blockStack; | 1260 curr = m_blockStack; |
| 1261 } | 1261 } |
| 1262 | 1262 |
| 1263 reopenResidualStyleTags(residualStyleStack, 0); // Stray table content can't
be an issue here, since some element above will always become the root of new s
tray table content. | 1263 reopenResidualStyleTags(residualStyleStack, 0); // Stray table content can't
be an issue here, since some element above will always become the root of new s
tray table content. |
| 1264 | 1264 |
| 1265 m_handlingResidualStyleAcrossBlocks = false; | 1265 m_handlingResidualStyleAcrossBlocks = false; |
| 1266 } | 1266 } |
| 1267 | 1267 |
| 1268 void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
leParent) | 1268 void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
leParent) |
| 1269 { | 1269 { |
| 1270 // Loop for each tag that needs to be reopened. | 1270 // Loop for each tag that needs to be reopened. |
| 1271 while (elem) { | 1271 while (elem) { |
| 1272 // Create a shallow clone of the DOM node for this element. | 1272 // Create a shallow clone of the DOM node for this element. |
| 1273 RefPtr<Node> newNode = elem->node->cloneNode(false); | 1273 RefPtr<Node> newNode = elem->node->cloneNode(false); |
| 1274 reportError(ResidualStyleError, &newNode->localName()); | 1274 reportError(ResidualStyleError, &newNode->localName()); |
| 1275 | 1275 |
| 1276 // Append the new node. In the malformed table case, we need to insert b
efore the table, | 1276 // Append the new node. In the malformed table case, we need to insert b
efore the table, |
| 1277 // which will be the last child. | 1277 // which will be the last child. |
| 1278 ExceptionCode ec = 0; | 1278 ExceptionCode ec = 0; |
| 1279 if (malformedTableParent) | 1279 if (malformedTableParent) |
| 1280 malformedTableParent->insertBefore(newNode, malformedTableParent->la
stChild(), ec); | 1280 malformedTableParent->insertBefore(newNode, malformedTableParent->la
stChild(), ec); |
| 1281 else | 1281 else |
| 1282 current->appendChild(newNode, ec); | 1282 m_current->appendChild(newNode, ec); |
| 1283 // FIXME: Is it really OK to ignore the exceptions here? | 1283 // FIXME: Is it really OK to ignore the exceptions here? |
| 1284 | 1284 |
| 1285 // Now push a new stack element for this node we just created. | 1285 // Now push a new stack element for this node we just created. |
| 1286 pushBlock(elem->tagName, elem->level); | 1286 pushBlock(elem->tagName, elem->level); |
| 1287 newNode->beginParsingChildren(); | 1287 newNode->beginParsingChildren(); |
| 1288 | 1288 |
| 1289 // Set our strayTableContent boolean if needed, so that the reopened tag
also knows | 1289 // Set our strayTableContent boolean if needed, so that the reopened tag
also knows |
| 1290 // that it is inside a malformed table. | 1290 // that it is inside a malformed table. |
| 1291 blockStack->strayTableContent = malformedTableParent != 0; | 1291 m_blockStack->strayTableContent = malformedTableParent != 0; |
| 1292 if (blockStack->strayTableContent) | 1292 if (m_blockStack->strayTableContent) |
| 1293 inStrayTableContent++; | 1293 m_inStrayTableContent++; |
| 1294 | 1294 |
| 1295 // Clear our malformed table parent variable. | 1295 // Clear our malformed table parent variable. |
| 1296 malformedTableParent = 0; | 1296 malformedTableParent = 0; |
| 1297 | 1297 |
| 1298 // Update |current| manually to point to the new node. | 1298 // Update |current| manually to point to the new node. |
| 1299 setCurrent(newNode.get()); | 1299 setCurrent(newNode.get()); |
| 1300 | 1300 |
| 1301 // Advance to the next tag that needs to be reopened. | 1301 // Advance to the next tag that needs to be reopened. |
| 1302 HTMLStackElem* next = elem->next; | 1302 HTMLStackElem* next = elem->next; |
| 1303 elem->derefNode(); | 1303 elem->derefNode(); |
| 1304 delete elem; | 1304 delete elem; |
| 1305 elem = next; | 1305 elem = next; |
| 1306 } | 1306 } |
| 1307 } | 1307 } |
| 1308 | 1308 |
| 1309 void HTMLParser::pushBlock(const AtomicString& tagName, int level) | 1309 void HTMLParser::pushBlock(const AtomicString& tagName, int level) |
| 1310 { | 1310 { |
| 1311 blockStack = new HTMLStackElem(tagName, level, current, didRefCurrent, block
Stack); | 1311 m_blockStack = new HTMLStackElem(tagName, level, m_current, m_didRefCurrent,
m_blockStack); |
| 1312 didRefCurrent = false; | 1312 m_didRefCurrent = false; |
| 1313 if (tagName == pTag) | 1313 if (tagName == pTag) |
| 1314 m_hasPElementInScope = InScope; | 1314 m_hasPElementInScope = InScope; |
| 1315 else if (isScopingTag(tagName)) | 1315 else if (isScopingTag(tagName)) |
| 1316 m_hasPElementInScope = NotInScope; | 1316 m_hasPElementInScope = NotInScope; |
| 1317 } | 1317 } |
| 1318 | 1318 |
| 1319 void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors) | 1319 void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors) |
| 1320 { | 1320 { |
| 1321 HTMLStackElem* elem = blockStack; | 1321 HTMLStackElem* elem = m_blockStack; |
| 1322 | 1322 |
| 1323 int maxLevel = 0; | 1323 int maxLevel = 0; |
| 1324 | 1324 |
| 1325 while (elem && (elem->tagName != tagName)) { | 1325 while (elem && (elem->tagName != tagName)) { |
| 1326 if (maxLevel < elem->level) | 1326 if (maxLevel < elem->level) |
| 1327 maxLevel = elem->level; | 1327 maxLevel = elem->level; |
| 1328 elem = elem->next; | 1328 elem = elem->next; |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 if (!elem) { | 1331 if (!elem) { |
| 1332 if (reportErrors) | 1332 if (reportErrors) |
| 1333 reportError(StrayCloseTagError, &tagName, 0, true); | 1333 reportError(StrayCloseTagError, &tagName, 0, true); |
| 1334 return; | 1334 return; |
| 1335 } | 1335 } |
| 1336 | 1336 |
| 1337 if (maxLevel > elem->level) { | 1337 if (maxLevel > elem->level) { |
| 1338 // We didn't match because the tag is in a different scope, e.g., | 1338 // We didn't match because the tag is in a different scope, e.g., |
| 1339 // <b><p>Foo</b>. Try to correct the problem. | 1339 // <b><p>Foo</b>. Try to correct the problem. |
| 1340 if (!isResidualStyleTag(tagName)) | 1340 if (!isResidualStyleTag(tagName)) |
| 1341 return; | 1341 return; |
| 1342 return handleResidualStyleCloseTagAcrossBlocks(elem); | 1342 return handleResidualStyleCloseTagAcrossBlocks(elem); |
| 1343 } | 1343 } |
| 1344 | 1344 |
| 1345 bool isAffectedByStyle = isAffectedByResidualStyle(elem->tagName); | 1345 bool isAffectedByStyle = isAffectedByResidualStyle(elem->tagName); |
| 1346 HTMLStackElem* residualStyleStack = 0; | 1346 HTMLStackElem* residualStyleStack = 0; |
| 1347 Node* malformedTableParent = 0; | 1347 Node* malformedTableParent = 0; |
| 1348 | 1348 |
| 1349 elem = blockStack; | 1349 elem = m_blockStack; |
| 1350 unsigned stackDepth = 1; | 1350 unsigned stackDepth = 1; |
| 1351 unsigned redundantStyleCount = 0; | 1351 unsigned redundantStyleCount = 0; |
| 1352 while (elem) { | 1352 while (elem) { |
| 1353 if (elem->tagName == tagName) { | 1353 if (elem->tagName == tagName) { |
| 1354 int strayTable = inStrayTableContent; | 1354 int strayTable = m_inStrayTableContent; |
| 1355 popOneBlock(); | 1355 popOneBlock(); |
| 1356 elem = 0; | 1356 elem = 0; |
| 1357 | 1357 |
| 1358 // This element was the root of some malformed content just inside a
n implicit or | 1358 // This element was the root of some malformed content just inside a
n implicit or |
| 1359 // explicit <tbody> or <tr>. | 1359 // explicit <tbody> or <tr>. |
| 1360 // If we end up needing to reopen residual style tags, the root of t
he reopened chain | 1360 // If we end up needing to reopen residual style tags, the root of t
he reopened chain |
| 1361 // must also know that it is the root of malformed content inside a
<tbody>/<tr>. | 1361 // must also know that it is the root of malformed content inside a
<tbody>/<tr>. |
| 1362 if (strayTable && (inStrayTableContent < strayTable) && residualStyl
eStack) { | 1362 if (strayTable && (m_inStrayTableContent < strayTable) && residualSt
yleStack) { |
| 1363 Node* curr = current; | 1363 Node* curr = m_current; |
| 1364 while (curr && !curr->hasTagName(tableTag)) | 1364 while (curr && !curr->hasTagName(tableTag)) |
| 1365 curr = curr->parentNode(); | 1365 curr = curr->parentNode(); |
| 1366 malformedTableParent = curr ? curr->parentNode() : 0; | 1366 malformedTableParent = curr ? curr->parentNode() : 0; |
| 1367 } | 1367 } |
| 1368 } | 1368 } |
| 1369 else { | 1369 else { |
| 1370 if (m_currentFormElement && elem->tagName == formTag) | 1370 if (m_currentFormElement && elem->tagName == formTag) |
| 1371 // A <form> is being closed prematurely (and this is | 1371 // A <form> is being closed prematurely (and this is |
| 1372 // malformed HTML). Set an attribute on the form to clear out i
ts | 1372 // malformed HTML). Set an attribute on the form to clear out i
ts |
| 1373 // bottom margin. | 1373 // bottom margin. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1388 redundantStyleCount++; | 1388 redundantStyleCount++; |
| 1389 else | 1389 else |
| 1390 redundantStyleCount = 0; | 1390 redundantStyleCount = 0; |
| 1391 | 1391 |
| 1392 if (redundantStyleCount < cMaxRedundantTagDepth) | 1392 if (redundantStyleCount < cMaxRedundantTagDepth) |
| 1393 moveOneBlockToStack(residualStyleStack); | 1393 moveOneBlockToStack(residualStyleStack); |
| 1394 else | 1394 else |
| 1395 popOneBlock(); | 1395 popOneBlock(); |
| 1396 } else | 1396 } else |
| 1397 popOneBlock(); | 1397 popOneBlock(); |
| 1398 elem = blockStack; | 1398 elem = m_blockStack; |
| 1399 } | 1399 } |
| 1400 } | 1400 } |
| 1401 | 1401 |
| 1402 reopenResidualStyleTags(residualStyleStack, malformedTableParent); | 1402 reopenResidualStyleTags(residualStyleStack, malformedTableParent); |
| 1403 } | 1403 } |
| 1404 | 1404 |
| 1405 inline HTMLStackElem* HTMLParser::popOneBlockCommon() | 1405 inline HTMLStackElem* HTMLParser::popOneBlockCommon() |
| 1406 { | 1406 { |
| 1407 HTMLStackElem* elem = blockStack; | 1407 HTMLStackElem* elem = m_blockStack; |
| 1408 | 1408 |
| 1409 // Form elements restore their state during the parsing process. | 1409 // Form elements restore their state during the parsing process. |
| 1410 // Also, a few elements (<applet>, <object>) need to know when all child ele
ments (<param>s) are available. | 1410 // Also, a few elements (<applet>, <object>) need to know when all child ele
ments (<param>s) are available. |
| 1411 if (current && elem->node != current) | 1411 if (m_current && elem->node != m_current) |
| 1412 current->finishParsingChildren(); | 1412 m_current->finishParsingChildren(); |
| 1413 | 1413 |
| 1414 blockStack = elem->next; | 1414 m_blockStack = elem->next; |
| 1415 current = elem->node; | 1415 m_current = elem->node; |
| 1416 didRefCurrent = elem->didRefNode; | 1416 m_didRefCurrent = elem->didRefNode; |
| 1417 | 1417 |
| 1418 if (elem->strayTableContent) | 1418 if (elem->strayTableContent) |
| 1419 inStrayTableContent--; | 1419 m_inStrayTableContent--; |
| 1420 | 1420 |
| 1421 if (elem->tagName == pTag) | 1421 if (elem->tagName == pTag) |
| 1422 m_hasPElementInScope = NotInScope; | 1422 m_hasPElementInScope = NotInScope; |
| 1423 else if (isScopingTag(elem->tagName)) | 1423 else if (isScopingTag(elem->tagName)) |
| 1424 m_hasPElementInScope = Unknown; | 1424 m_hasPElementInScope = Unknown; |
| 1425 | 1425 |
| 1426 return elem; | 1426 return elem; |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 void HTMLParser::popOneBlock() | 1429 void HTMLParser::popOneBlock() |
| 1430 { | 1430 { |
| 1431 // Store the current node before popOneBlockCommon overwrites it. | 1431 // Store the current node before popOneBlockCommon overwrites it. |
| 1432 Node* lastCurrent = current; | 1432 Node* lastCurrent = m_current; |
| 1433 bool didRefLastCurrent = didRefCurrent; | 1433 bool didRefLastCurrent = m_didRefCurrent; |
| 1434 | 1434 |
| 1435 delete popOneBlockCommon(); | 1435 delete popOneBlockCommon(); |
| 1436 | 1436 |
| 1437 if (didRefLastCurrent) | 1437 if (didRefLastCurrent) |
| 1438 lastCurrent->deref(); | 1438 lastCurrent->deref(); |
| 1439 } | 1439 } |
| 1440 | 1440 |
| 1441 void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head) | 1441 void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head) |
| 1442 { | 1442 { |
| 1443 // We'll be using the stack element we're popping, but for the current node. | 1443 // We'll be using the stack element we're popping, but for the current node. |
| 1444 // See the two callers for details. | 1444 // See the two callers for details. |
| 1445 | 1445 |
| 1446 // Store the current node before popOneBlockCommon overwrites it. | 1446 // Store the current node before popOneBlockCommon overwrites it. |
| 1447 Node* lastCurrent = current; | 1447 Node* lastCurrent = m_current; |
| 1448 bool didRefLastCurrent = didRefCurrent; | 1448 bool didRefLastCurrent = m_didRefCurrent; |
| 1449 | 1449 |
| 1450 // Pop the block, but don't deref the current node as popOneBlock does becau
se | 1450 // Pop the block, but don't deref the current node as popOneBlock does becau
se |
| 1451 // we'll be using the pointer in the new stack element. | 1451 // we'll be using the pointer in the new stack element. |
| 1452 HTMLStackElem* elem = popOneBlockCommon(); | 1452 HTMLStackElem* elem = popOneBlockCommon(); |
| 1453 | 1453 |
| 1454 // Transfer the current node into the stack element. | 1454 // Transfer the current node into the stack element. |
| 1455 // No need to deref the old elem->node because popOneBlockCommon transferred | 1455 // No need to deref the old elem->node because popOneBlockCommon transferred |
| 1456 // it into the current/didRefCurrent fields. | 1456 // it into the m_current/m_didRefCurrent fields. |
| 1457 elem->node = lastCurrent; | 1457 elem->node = lastCurrent; |
| 1458 elem->didRefNode = didRefLastCurrent; | 1458 elem->didRefNode = didRefLastCurrent; |
| 1459 elem->next = head; | 1459 elem->next = head; |
| 1460 head = elem; | 1460 head = elem; |
| 1461 } | 1461 } |
| 1462 | 1462 |
| 1463 void HTMLParser::checkIfHasPElementInScope() | 1463 void HTMLParser::checkIfHasPElementInScope() |
| 1464 { | 1464 { |
| 1465 m_hasPElementInScope = NotInScope; | 1465 m_hasPElementInScope = NotInScope; |
| 1466 HTMLStackElem* elem = blockStack; | 1466 HTMLStackElem* elem = m_blockStack; |
| 1467 while (elem) { | 1467 while (elem) { |
| 1468 const AtomicString& tagName = elem->tagName; | 1468 const AtomicString& tagName = elem->tagName; |
| 1469 if (tagName == pTag) { | 1469 if (tagName == pTag) { |
| 1470 m_hasPElementInScope = InScope; | 1470 m_hasPElementInScope = InScope; |
| 1471 return; | 1471 return; |
| 1472 } else if (isScopingTag(tagName)) | 1472 } else if (isScopingTag(tagName)) |
| 1473 return; | 1473 return; |
| 1474 elem = elem->next; | 1474 elem = elem->next; |
| 1475 } | 1475 } |
| 1476 } | 1476 } |
| 1477 | 1477 |
| 1478 void HTMLParser::popInlineBlocks() | 1478 void HTMLParser::popInlineBlocks() |
| 1479 { | 1479 { |
| 1480 while (blockStack && isInline(current)) | 1480 while (m_blockStack && isInline(m_current)) |
| 1481 popOneBlock(); | 1481 popOneBlock(); |
| 1482 } | 1482 } |
| 1483 | 1483 |
| 1484 void HTMLParser::freeBlock() | 1484 void HTMLParser::freeBlock() |
| 1485 { | 1485 { |
| 1486 while (blockStack) | 1486 while (m_blockStack) |
| 1487 popOneBlock(); | 1487 popOneBlock(); |
| 1488 } | 1488 } |
| 1489 | 1489 |
| 1490 void HTMLParser::createHead() | 1490 void HTMLParser::createHead() |
| 1491 { | 1491 { |
| 1492 if (head || !document->documentElement()) | 1492 if (m_head || !m_document->documentElement()) |
| 1493 return; | 1493 return; |
| 1494 | 1494 |
| 1495 head = new HTMLHeadElement(headTag, document); | 1495 m_head = new HTMLHeadElement(headTag, m_document); |
| 1496 HTMLElement* body = document->body(); | 1496 HTMLElement* body = m_document->body(); |
| 1497 ExceptionCode ec = 0; | 1497 ExceptionCode ec = 0; |
| 1498 document->documentElement()->insertBefore(head, body, ec); | 1498 m_document->documentElement()->insertBefore(m_head, body, ec); |
| 1499 if (ec) | 1499 if (ec) |
| 1500 head = 0; | 1500 m_head = 0; |
| 1501 | 1501 |
| 1502 // If the body does not exist yet, then the <head> should be pushed as the c
urrent block. | 1502 // If the body does not exist yet, then the <head> should be pushed as the c
urrent block. |
| 1503 if (head && !body) { | 1503 if (m_head && !body) { |
| 1504 pushBlock(head->localName(), head->tagPriority()); | 1504 pushBlock(m_head->localName(), m_head->tagPriority()); |
| 1505 setCurrent(head); | 1505 setCurrent(m_head); |
| 1506 } | 1506 } |
| 1507 } | 1507 } |
| 1508 | 1508 |
| 1509 PassRefPtr<Node> HTMLParser::handleIsindex(Token* t) | 1509 PassRefPtr<Node> HTMLParser::handleIsindex(Token* t) |
| 1510 { | 1510 { |
| 1511 RefPtr<Node> n = new HTMLDivElement(divTag, document); | 1511 RefPtr<Node> n = new HTMLDivElement(divTag, m_document); |
| 1512 | 1512 |
| 1513 NamedMappedAttrMap* attrs = t->attrs.get(); | 1513 NamedMappedAttrMap* attrs = t->attrs.get(); |
| 1514 | 1514 |
| 1515 RefPtr<HTMLIsIndexElement> isIndex = new HTMLIsIndexElement(isindexTag, docu
ment, m_currentFormElement.get()); | 1515 RefPtr<HTMLIsIndexElement> isIndex = new HTMLIsIndexElement(isindexTag, m_do
cument, m_currentFormElement.get()); |
| 1516 isIndex->setAttributeMap(attrs); | 1516 isIndex->setAttributeMap(attrs); |
| 1517 isIndex->setAttribute(typeAttr, "khtml_isindex"); | 1517 isIndex->setAttribute(typeAttr, "khtml_isindex"); |
| 1518 | 1518 |
| 1519 String text = searchableIndexIntroduction(); | 1519 String text = searchableIndexIntroduction(); |
| 1520 if (attrs) { | 1520 if (attrs) { |
| 1521 if (Attribute* a = attrs->getAttributeItem(promptAttr)) | 1521 if (Attribute* a = attrs->getAttributeItem(promptAttr)) |
| 1522 text = a->value().string() + " "; | 1522 text = a->value().string() + " "; |
| 1523 t->attrs = 0; | 1523 t->attrs = 0; |
| 1524 } | 1524 } |
| 1525 | 1525 |
| 1526 n->addChild(new HTMLHRElement(hrTag, document)); | 1526 n->addChild(new HTMLHRElement(hrTag, m_document)); |
| 1527 n->addChild(new Text(document, text)); | 1527 n->addChild(new Text(m_document, text)); |
| 1528 n->addChild(isIndex.release()); | 1528 n->addChild(isIndex.release()); |
| 1529 n->addChild(new HTMLHRElement(hrTag, document)); | 1529 n->addChild(new HTMLHRElement(hrTag, m_document)); |
| 1530 | 1530 |
| 1531 return n.release(); | 1531 return n.release(); |
| 1532 } | 1532 } |
| 1533 | 1533 |
| 1534 void HTMLParser::startBody() | 1534 void HTMLParser::startBody() |
| 1535 { | 1535 { |
| 1536 if (inBody) | 1536 if (m_inBody) |
| 1537 return; | 1537 return; |
| 1538 | 1538 |
| 1539 inBody = true; | 1539 m_inBody = true; |
| 1540 | 1540 |
| 1541 if (m_isindexElement) { | 1541 if (m_isindexElement) { |
| 1542 insertNode(m_isindexElement.get(), true /* don't descend into this node
*/); | 1542 insertNode(m_isindexElement.get(), true /* don't descend into this node
*/); |
| 1543 m_isindexElement = 0; | 1543 m_isindexElement = 0; |
| 1544 } | 1544 } |
| 1545 } | 1545 } |
| 1546 | 1546 |
| 1547 void HTMLParser::finished() | 1547 void HTMLParser::finished() |
| 1548 { | 1548 { |
| 1549 // In the case of a completely empty document, here's the place to create th
e HTML element. | 1549 // In the case of a completely empty document, here's the place to create th
e HTML element. |
| 1550 if (current && current->isDocumentNode() && !document->documentElement()) | 1550 if (m_current && m_current->isDocumentNode() && !m_document->documentElement
()) |
| 1551 insertNode(new HTMLHtmlElement(htmlTag, document)); | 1551 insertNode(new HTMLHtmlElement(htmlTag, m_document)); |
| 1552 | 1552 |
| 1553 // This ensures that "current" is not left pointing to a node when the docum
ent is destroyed. | 1553 // This ensures that "current" is not left pointing to a node when the docum
ent is destroyed. |
| 1554 freeBlock(); | 1554 freeBlock(); |
| 1555 setCurrent(0); | 1555 setCurrent(0); |
| 1556 | 1556 |
| 1557 // Warning, this may delete the tokenizer and parser, so don't try to do any
thing else after this. | 1557 // Warning, this may delete the tokenizer and parser, so don't try to do any
thing else after this. |
| 1558 if (!m_isParsingFragment) | 1558 if (!m_isParsingFragment) |
| 1559 document->finishedParsing(); | 1559 m_document->finishedParsing(); |
| 1560 } | 1560 } |
| 1561 | 1561 |
| 1562 void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const Atomi
cString* tagName1, const AtomicString* tagName2, bool closeTags) | 1562 void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const Atomi
cString* tagName1, const AtomicString* tagName2, bool closeTags) |
| 1563 { | 1563 { |
| 1564 Frame* frame = document->frame(); | 1564 Frame* frame = m_document->frame(); |
| 1565 if (!frame) | 1565 if (!frame) |
| 1566 return; | 1566 return; |
| 1567 | 1567 |
| 1568 HTMLTokenizer* htmlTokenizer = static_cast<HTMLTokenizer*>(document->tokeniz
er()); | 1568 HTMLTokenizer* htmlTokenizer = static_cast<HTMLTokenizer*>(m_document->token
izer()); |
| 1569 int lineNumber = htmlTokenizer->lineNumber() + 1; | 1569 int lineNumber = htmlTokenizer->lineNumber() + 1; |
| 1570 | 1570 |
| 1571 AtomicString tag1; | 1571 AtomicString tag1; |
| 1572 AtomicString tag2; | 1572 AtomicString tag2; |
| 1573 if (tagName1) { | 1573 if (tagName1) { |
| 1574 if (*tagName1 == "#text") | 1574 if (*tagName1 == "#text") |
| 1575 tag1 = "Text"; | 1575 tag1 = "Text"; |
| 1576 else if (*tagName1 == "#comment") | 1576 else if (*tagName1 == "#comment") |
| 1577 tag1 = "<!-- comment -->"; | 1577 tag1 = "<!-- comment -->"; |
| 1578 else | 1578 else |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1593 | 1593 |
| 1594 String message; | 1594 String message; |
| 1595 if (htmlTokenizer->processingContentWrittenByScript()) | 1595 if (htmlTokenizer->processingContentWrittenByScript()) |
| 1596 message += htmlParserDocumentWriteMessage(); | 1596 message += htmlParserDocumentWriteMessage(); |
| 1597 message += errorMsg; | 1597 message += errorMsg; |
| 1598 message.replace("%tag1", tag1); | 1598 message.replace("%tag1", tag1); |
| 1599 message.replace("%tag2", tag2); | 1599 message.replace("%tag2", tag2); |
| 1600 | 1600 |
| 1601 frame->domWindow()->console()->addMessage(HTMLMessageSource, | 1601 frame->domWindow()->console()->addMessage(HTMLMessageSource, |
| 1602 isWarning(errorCode) ? WarningMessageLevel : ErrorMessageLevel, | 1602 isWarning(errorCode) ? WarningMessageLevel : ErrorMessageLevel, |
| 1603 message, lineNumber, document->url().string()); | 1603 message, lineNumber, m_document->url().string()); |
| 1604 } | 1604 } |
| 1605 | 1605 |
| 1606 } | 1606 } |
| 1607 | 1607 |
| 1608 | 1608 |
| OLD | NEW |