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 |