Changeset 80201 in webkit
- Timestamp:
- Mar 2, 2011 8:40:56 PM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r80200 r80201 1 2011-03-02 Andy Estes <aestes@apple.com> 2 3 Reviewed by Eric Seidel. 4 5 HTML5 TreeBuilder regressed a Peacekeeper DOM test by 25% (was 40%) 6 https://bugs.webkit.org/show_bug.cgi?id=48719 7 8 Instead of pushing a fake HTMLHtmlElement onto the open element stack 9 during fragment parsing only to later remove it and reparent its 10 children to the DocumentFragment, push the DocumentFragment directly 11 onto the open element stack as the root node. This requires refactoring 12 HTMLElementStack to hold ContainerNode pointers rather than Element 13 pointers, which has implications for HTMLConstructionSite and 14 HTMLTreeBuilder as well. 15 16 With this patch, the regression in Peacekeeper due to the introduction 17 of the HTML5 fragment parsing algorithm is ~14%. The regression from 18 Safari 5.0.3 is ~24%. 19 20 No new tests. No change in behavior. 21 22 * dom/Element.h: 23 (WebCore::Node::hasLocalName): 24 * dom/Node.h: 25 * html/parser/HTMLConstructionSite.cpp: 26 (WebCore::HTMLNames::hasImpliedEndTag): 27 (WebCore::HTMLConstructionSite::HTMLConstructionSite): 28 (WebCore::HTMLConstructionSite::insertHTMLHtmlStartTagInBody): 29 (WebCore::HTMLConstructionSite::insertComment): 30 (WebCore::HTMLConstructionSite::insertCommentOnHTMLHtmlElement): 31 (WebCore::HTMLConstructionSite::attachToCurrent): 32 (WebCore::HTMLConstructionSite::insertScriptElement): 33 (WebCore::HTMLConstructionSite::insertTextNode): 34 (WebCore::HTMLConstructionSite::createElement): 35 (WebCore::HTMLConstructionSite::createHTMLElement): 36 (WebCore::HTMLConstructionSite::generateImpliedEndTagsWithExclusion): 37 (WebCore::HTMLConstructionSite::generateImpliedEndTags): 38 (WebCore::HTMLConstructionSite::findFosterSite): 39 (WebCore::HTMLConstructionSite::shouldFosterParent): 40 * html/parser/HTMLConstructionSite.h: 41 (WebCore::HTMLConstructionSite::currentNode): 42 * html/parser/HTMLElementStack.cpp: 43 (WebCore::HTMLNames::isNumberedHeaderElement): 44 (WebCore::HTMLNames::isScopeMarker): 45 (WebCore::HTMLNames::isListItemScopeMarker): 46 (WebCore::HTMLNames::isTableScopeMarker): 47 (WebCore::HTMLNames::isTableBodyScopeMarker): 48 (WebCore::HTMLNames::isTableRowScopeMarker): 49 (WebCore::HTMLNames::isButtonScopeMarker): 50 (WebCore::HTMLNames::isSelectScopeMarker): 51 (WebCore::HTMLElementStack::ElementRecord::ElementRecord): 52 (WebCore::HTMLElementStack::ElementRecord::replaceElement): 53 (WebCore::HTMLElementStack::HTMLElementStack): 54 (WebCore::HTMLElementStack::secondElementIsHTMLBodyElement): 55 (WebCore::HTMLElementStack::popAll): 56 (WebCore::HTMLElementStack::popUntilNumberedHeaderElementPopped): 57 (WebCore::HTMLElementStack::popUntil): 58 (WebCore::HTMLElementStack::popUntilPopped): 59 (WebCore::HTMLElementStack::popUntilTableScopeMarker): 60 (WebCore::HTMLElementStack::popUntilTableBodyScopeMarker): 61 (WebCore::HTMLElementStack::popUntilTableRowScopeMarker): 62 (WebCore::HTMLElementStack::pushHTMLHtmlElement): 63 (WebCore::HTMLElementStack::push): 64 (WebCore::HTMLElementStack::insertAbove): 65 (WebCore::HTMLElementStack::find): 66 (WebCore::HTMLElementStack::topmost): 67 (WebCore::HTMLElementStack::contains): 68 (WebCore::inScopeCommon): 69 (WebCore::HTMLElementStack::hasNumberedHeaderElementInScope): 70 (WebCore::HTMLElementStack::htmlElement): 71 (WebCore::HTMLElementStack::rootNode): 72 (WebCore::HTMLElementStack::pushCommon): 73 * html/parser/HTMLElementStack.h: 74 (WebCore::HTMLElementStack::ElementRecord::element): 75 (WebCore::HTMLElementStack::ElementRecord::node): 76 (WebCore::HTMLElementStack::topNode): 77 * html/parser/HTMLTreeBuilder.cpp: 78 (WebCore::HTMLTreeBuilder::HTMLTreeBuilder): 79 (WebCore::HTMLTreeBuilder::processCloseWhenNestedTag): 80 (WebCore::HTMLTreeBuilder::processStartTagForInBody): 81 (WebCore::HTMLTreeBuilder::processColgroupEndTagForInColumnGroup): 82 (WebCore::HTMLTreeBuilder::processStartTag): 83 (WebCore::HTMLTreeBuilder::processAnyOtherEndTagForInBody): 84 (WebCore::HTMLTreeBuilder::callTheAdoptionAgency): 85 (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately): 86 (WebCore::HTMLTreeBuilder::processEndTagForInCell): 87 (WebCore::HTMLTreeBuilder::processEndTagForInBody): 88 (WebCore::HTMLTreeBuilder::processEndTag): 89 (WebCore::HTMLTreeBuilder::processEndOfFile): 90 (WebCore::HTMLTreeBuilder::finished): 91 * html/parser/HTMLTreeBuilder.h: 92 1 93 2011-03-02 Sheriff Bot <webkit.review.bot@gmail.com> 2 94 -
trunk/Source/WebCore/dom/Element.h
r80030 r80201 428 428 return isElementNode() && toElement(this)->hasTagName(name); 429 429 } 430 431 inline bool Node::hasLocalName(const AtomicString& name) const 432 { 433 return isElementNode() && toElement(this)->hasLocalName(name); 434 } 430 435 431 436 inline bool Node::hasAttributes() const -
trunk/Source/WebCore/dom/Node.h
r79269 r80201 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 7 7 * … … 135 135 136 136 bool hasTagName(const QualifiedName&) const; 137 bool hasLocalName(const AtomicString&) const; 137 138 virtual String nodeName() const = 0; 138 139 virtual String nodeValue() const; -
trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp
r78286 r80201 1 1 /* 2 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 59 60 namespace { 60 61 61 bool hasImpliedEndTag( Element* element)62 { 63 return element->hasTagName(ddTag)64 || element->hasTagName(dtTag)65 || element->hasTagName(liTag)66 || element->hasTagName(optionTag)67 || element->hasTagName(optgroupTag)68 || element->hasTagName(pTag)69 || element->hasTagName(rpTag)70 || element->hasTagName(rtTag);62 bool hasImpliedEndTag(ContainerNode* node) 63 { 64 return node->hasTagName(ddTag) 65 || node->hasTagName(dtTag) 66 || node->hasTagName(liTag) 67 || node->hasTagName(optionTag) 68 || node->hasTagName(optgroupTag) 69 || node->hasTagName(pTag) 70 || node->hasTagName(rpTag) 71 || node->hasTagName(rtTag); 71 72 } 72 73 … … 205 206 { 206 207 // FIXME: parse error 208 209 // Fragments do not have a root HTML element, so any additional HTML elements 210 // encountered during fragment parsing should be ignored. 211 if (m_isParsingFragment) 212 return; 213 207 214 mergeAttributesFromTokenIntoElement(token, m_openElements.htmlElement()); 208 215 } … … 237 244 { 238 245 ASSERT(token.type() == HTMLToken::Comment); 239 attach(current Element(), Comment::create(currentElement()->document(), token.comment()));246 attach(currentNode(), Comment::create(currentNode()->document(), token.comment())); 240 247 } 241 248 … … 249 256 { 250 257 ASSERT(token.type() == HTMLToken::Comment); 251 Element* parent = m_openElements.htmlElement();258 ContainerNode* parent = m_openElements.rootNode(); 252 259 attach(parent, Comment::create(parent->document(), token.comment())); 253 260 } … … 255 262 PassRefPtr<Element> HTMLConstructionSite::attachToCurrent(PassRefPtr<Element> child) 256 263 { 257 return attach(current Element(), child);264 return attach(currentNode(), child); 258 265 } 259 266 … … 311 318 void HTMLConstructionSite::insertScriptElement(AtomicHTMLToken& token) 312 319 { 313 RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, current Element()->document(), true);320 RefPtr<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, currentNode()->document(), true); 314 321 if (m_fragmentScriptingPermission == FragmentScriptingAllowed) 315 322 element->setAttributeMap(token.takeAtributes(), m_fragmentScriptingPermission); … … 330 337 { 331 338 AttachmentSite site; 332 site.parent = current Element();339 site.parent = currentNode(); 333 340 site.nextChild = 0; 334 341 if (shouldFosterParent()) … … 350 357 { 351 358 QualifiedName tagName(nullAtom, token.name(), namespaceURI); 352 RefPtr<Element> element = current Element()->document()->createElement(tagName, true);359 RefPtr<Element> element = currentNode()->document()->createElement(tagName, true); 353 360 element->setAttributeMap(token.takeAtributes(), m_fragmentScriptingPermission); 354 361 return element.release(); … … 361 368 // have to pass the current form element. We should rework form association 362 369 // to occur after construction to allow better code sharing here. 363 RefPtr<Element> element = HTMLElementFactory::createHTMLElement(tagName, current Element()->document(), form(), true);370 RefPtr<Element> element = HTMLElementFactory::createHTMLElement(tagName, currentNode()->document(), form(), true); 364 371 element->setAttributeMap(token.takeAtributes(), m_fragmentScriptingPermission); 365 372 ASSERT(element->isHTMLElement()); … … 440 447 void HTMLConstructionSite::generateImpliedEndTagsWithExclusion(const AtomicString& tagName) 441 448 { 442 while (hasImpliedEndTag(current Element()) && !currentElement()->hasLocalName(tagName))449 while (hasImpliedEndTag(currentNode()) && !currentNode()->hasLocalName(tagName)) 443 450 m_openElements.pop(); 444 451 } … … 446 453 void HTMLConstructionSite::generateImpliedEndTags() 447 454 { 448 while (hasImpliedEndTag(current Element()))455 while (hasImpliedEndTag(currentNode())) 449 456 m_openElements.pop(); 450 457 } … … 465 472 } 466 473 // Fragment case 467 site.parent = m_openElements. bottom(); // <html> element474 site.parent = m_openElements.rootNode(); // DocumentFragment 468 475 site.nextChild = 0; 469 476 } … … 472 479 { 473 480 return m_redirectAttachToFosterParent 481 && currentNode()->isElementNode() 474 482 && causesFosterParenting(currentElement()->tagQName()); 475 483 } -
trunk/Source/WebCore/html/parser/HTMLConstructionSite.h
r78286 r80201 1 1 /* 2 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 81 82 82 83 Element* currentElement() const { return m_openElements.top(); } 84 ContainerNode* currentNode() const { return m_openElements.topNode(); } 83 85 Element* oneBelowTop() const { return m_openElements.oneBelowTop(); } 84 86 -
trunk/Source/WebCore/html/parser/HTMLElementStack.cpp
r70293 r80201 1 1 /* 2 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 27 28 #include "HTMLElementStack.h" 28 29 30 #include "DocumentFragment.h" 29 31 #include "Element.h" 30 32 #include "HTMLNames.h" … … 48 50 || element->hasTagName(h6Tag); 49 51 } 50 51 inline bool isScopeMarker(Element* element) 52 { 53 return element->hasTagName(appletTag) 54 || element->hasTagName(captionTag) 55 || element->hasTagName(htmlTag) 56 || element->hasTagName(marqueeTag) 57 || element->hasTagName(objectTag) 58 || element->hasTagName(tableTag) 59 || element->hasTagName(tdTag) 60 || element->hasTagName(thTag) 61 || element->hasTagName(MathMLNames::miTag) 62 || element->hasTagName(MathMLNames::moTag) 63 || element->hasTagName(MathMLNames::mnTag) 64 || element->hasTagName(MathMLNames::msTag) 65 || element->hasTagName(MathMLNames::mtextTag) 66 || element->hasTagName(MathMLNames::annotation_xmlTag) 67 || element->hasTagName(SVGNames::foreignObjectTag) 68 || element->hasTagName(SVGNames::descTag) 69 || element->hasTagName(SVGNames::titleTag); 70 } 71 72 inline bool isListItemScopeMarker(Element* element) 73 { 74 return isScopeMarker(element) 75 || element->hasTagName(olTag) 76 || element->hasTagName(ulTag); 77 } 78 79 inline bool isTableScopeMarker(Element* element) 80 { 81 return element->hasTagName(tableTag) 82 || element->hasTagName(htmlTag); 83 } 84 85 inline bool isTableBodyScopeMarker(Element* element) 86 { 87 return element->hasTagName(tbodyTag) 88 || element->hasTagName(tfootTag) 89 || element->hasTagName(theadTag) 90 || element->hasTagName(htmlTag); 91 } 92 93 inline bool isTableRowScopeMarker(Element* element) 94 { 95 return element->hasTagName(trTag) 96 || element->hasTagName(htmlTag); 52 53 inline bool isRootNode(ContainerNode* node) 54 { 55 return node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE 56 || node->hasTagName(htmlTag); 57 } 58 59 inline bool isScopeMarker(ContainerNode* node) 60 { 61 return node->hasTagName(appletTag) 62 || node->hasTagName(captionTag) 63 || node->hasTagName(marqueeTag) 64 || node->hasTagName(objectTag) 65 || node->hasTagName(tableTag) 66 || node->hasTagName(tdTag) 67 || node->hasTagName(thTag) 68 || node->hasTagName(MathMLNames::miTag) 69 || node->hasTagName(MathMLNames::moTag) 70 || node->hasTagName(MathMLNames::mnTag) 71 || node->hasTagName(MathMLNames::msTag) 72 || node->hasTagName(MathMLNames::mtextTag) 73 || node->hasTagName(MathMLNames::annotation_xmlTag) 74 || node->hasTagName(SVGNames::foreignObjectTag) 75 || node->hasTagName(SVGNames::descTag) 76 || node->hasTagName(SVGNames::titleTag) 77 || isRootNode(node); 78 } 79 80 inline bool isListItemScopeMarker(ContainerNode* node) 81 { 82 return isScopeMarker(node) 83 || node->hasTagName(olTag) 84 || node->hasTagName(ulTag); 85 } 86 87 inline bool isTableScopeMarker(ContainerNode* node) 88 { 89 return node->hasTagName(tableTag) 90 || isRootNode(node); 91 } 92 93 inline bool isTableBodyScopeMarker(ContainerNode* node) 94 { 95 return node->hasTagName(tbodyTag) 96 || node->hasTagName(tfootTag) 97 || node->hasTagName(theadTag) 98 || isRootNode(node); 99 } 100 101 inline bool isTableRowScopeMarker(ContainerNode* node) 102 { 103 return node->hasTagName(trTag) 104 || isRootNode(node); 97 105 } 98 106 … … 110 118 } 111 119 112 inline bool isButtonScopeMarker( Element* element)113 { 114 return isScopeMarker( element)115 || element->hasTagName(buttonTag);116 } 117 118 inline bool isSelectScopeMarker( Element* element)119 { 120 return ! element->hasTagName(optgroupTag)121 && ! element->hasTagName(optionTag);122 } 123 124 } 125 126 HTMLElementStack::ElementRecord::ElementRecord(PassRefPtr< Element> element, PassOwnPtr<ElementRecord> next)127 : m_ element(element)120 inline bool isButtonScopeMarker(ContainerNode* node) 121 { 122 return isScopeMarker(node) 123 || node->hasTagName(buttonTag); 124 } 125 126 inline bool isSelectScopeMarker(ContainerNode* node) 127 { 128 return !node->hasTagName(optgroupTag) 129 && !node->hasTagName(optionTag); 130 } 131 132 } 133 134 HTMLElementStack::ElementRecord::ElementRecord(PassRefPtr<ContainerNode> node, PassOwnPtr<ElementRecord> next) 135 : m_node(node) 128 136 , m_next(next) 129 137 { 130 ASSERT(m_ element);138 ASSERT(m_node); 131 139 } 132 140 … … 138 146 { 139 147 ASSERT(element); 148 ASSERT(!m_node || m_node->isElementNode()); 140 149 // FIXME: Should this call finishParsingChildren? 141 m_ element= element;150 m_node = element; 142 151 } 143 152 … … 152 161 153 162 HTMLElementStack::HTMLElementStack() 154 : m_ htmlElement(0)163 : m_rootNode(0) 155 164 , m_headElement(0) 156 165 , m_bodyElement(0) … … 172 181 // insertion mode. 173 182 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody 174 ASSERT(m_ htmlElement);183 ASSERT(m_rootNode); 175 184 // If we have a body element, it must always be the second element on the 176 185 // stack, as we always start with an html element, and any other element … … 195 204 void HTMLElementStack::popAll() 196 205 { 197 m_ htmlElement= 0;206 m_rootNode = 0; 198 207 m_headElement = 0; 199 208 m_bodyElement = 0; 200 209 while (m_top) { 201 top ()->finishParsingChildren();210 topNode()->finishParsingChildren(); 202 211 m_top = m_top->releaseNext(); 203 212 } … … 247 256 { 248 257 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-context 249 while (!isTableScopeMarker(top ()))258 while (!isTableScopeMarker(topNode())) 250 259 pop(); 251 260 } … … 254 263 { 255 264 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-body-context 256 while (!isTableBodyScopeMarker(top ()))265 while (!isTableBodyScopeMarker(topNode())) 257 266 pop(); 258 267 } … … 261 270 { 262 271 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-row-context 263 while (!isTableRowScopeMarker(top ()))272 while (!isTableRowScopeMarker(topNode())) 264 273 pop(); 265 274 } … … 270 279 pop(); 271 280 } 281 282 void HTMLElementStack::pushRootNode(PassRefPtr<ContainerNode> rootNode) 283 { 284 ASSERT(rootNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE); 285 pushRootNodeCommon(rootNode); 286 } 272 287 273 288 void HTMLElementStack::pushHTMLHtmlElement(PassRefPtr<Element> element) 274 289 { 275 ASSERT(!m_top); // <html> should always be the bottom of the stack.276 290 ASSERT(element->hasTagName(HTMLNames::htmlTag)); 277 ASSERT(!m_htmlElement); 278 m_htmlElement = element.get(); 279 pushCommon(element); 291 pushRootNodeCommon(element); 292 } 293 294 void HTMLElementStack::pushRootNodeCommon(PassRefPtr<ContainerNode> rootNode) 295 { 296 ASSERT(!m_top); 297 ASSERT(!m_rootNode); 298 m_rootNode = rootNode.get(); 299 pushCommon(rootNode); 280 300 } 281 301 … … 301 321 ASSERT(!element->hasTagName(HTMLNames::headTag)); 302 322 ASSERT(!element->hasTagName(HTMLNames::bodyTag)); 303 ASSERT(m_ htmlElement);323 ASSERT(m_rootNode); 304 324 pushCommon(element); 305 325 } … … 313 333 ASSERT(!element->hasTagName(HTMLNames::headTag)); 314 334 ASSERT(!element->hasTagName(HTMLNames::bodyTag)); 315 ASSERT(m_ htmlElement);335 ASSERT(m_rootNode); 316 336 if (recordBelow == m_top) { 317 337 push(element); … … 373 393 { 374 394 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { 375 if (pos-> element() == element)395 if (pos->node() == element) 376 396 return pos; 377 397 } … … 382 402 { 383 403 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { 384 if (pos-> element()->hasLocalName(tagName))404 if (pos->node()->hasLocalName(tagName)) 385 405 return pos; 386 406 } … … 398 418 } 399 419 400 template <bool isMarker( Element*)>420 template <bool isMarker(ContainerNode*)> 401 421 bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& targetTag) 402 422 { 403 423 for (HTMLElementStack::ElementRecord* pos = top; pos; pos = pos->next()) { 404 Element* element = pos->element();405 if ( element->hasLocalName(targetTag))424 ContainerNode* node = pos->node(); 425 if (node->hasLocalName(targetTag)) 406 426 return true; 407 if (isMarker( element))427 if (isMarker(node)) 408 428 return false; 409 429 } … … 428 448 { 429 449 for (ElementRecord* record = m_top.get(); record; record = record->next()) { 430 Element* element = record->element(); 431 if (isNumberedHeaderElement(element)) 450 if (isScopeMarker(record->node())) 451 return false; 452 if (isNumberedHeaderElement(record->element())) 432 453 return true; 433 if (isScopeMarker(element))434 return false;435 454 } 436 455 ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker. … … 508 527 Element* HTMLElementStack::htmlElement() const 509 528 { 510 ASSERT(m_ htmlElement);511 return m_htmlElement;529 ASSERT(m_rootNode); 530 return toElement(m_rootNode); 512 531 } 513 532 … … 523 542 return m_bodyElement; 524 543 } 525 526 void HTMLElementStack::pushCommon(PassRefPtr<Element> element) 527 { 528 ASSERT(m_htmlElement); 529 m_top = adoptPtr(new ElementRecord(element, m_top.release())); 530 top()->beginParsingChildren(); 544 545 ContainerNode* HTMLElementStack::rootNode() const 546 { 547 ASSERT(m_rootNode); 548 return m_rootNode; 549 } 550 551 void HTMLElementStack::pushCommon(PassRefPtr<ContainerNode> node) 552 { 553 ASSERT(m_rootNode); 554 m_top = adoptPtr(new ElementRecord(node, m_top.release())); 555 topNode()->beginParsingChildren(); 531 556 } 532 557 -
trunk/Source/WebCore/html/parser/HTMLElementStack.h
r76248 r80201 1 1 /* 2 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 27 28 #define HTMLElementStack_h 28 29 30 #include "Element.h" 29 31 #include <wtf/Forward.h> 30 32 #include <wtf/Noncopyable.h> … … 35 37 namespace WebCore { 36 38 39 class ContainerNode; 40 class DocumentFragment; 37 41 class Element; 38 42 class QualifiedName; … … 51 55 ~ElementRecord(); // Public for ~PassOwnPtr() 52 56 53 Element* element() const { return m_element.get(); } 57 Element* element() const { return toElement(m_node.get()); } 58 ContainerNode* node() const { return m_node.get(); } 54 59 void replaceElement(PassRefPtr<Element>); 55 60 … … 61 66 friend class HTMLElementStack; 62 67 63 ElementRecord(PassRefPtr< Element>, PassOwnPtr<ElementRecord>);68 ElementRecord(PassRefPtr<ContainerNode>, PassOwnPtr<ElementRecord>); 64 69 65 70 PassOwnPtr<ElementRecord> releaseNext() { return m_next.release(); } 66 71 void setNext(PassOwnPtr<ElementRecord> next) { m_next = next; } 67 72 68 RefPtr< Element> m_element;73 RefPtr<ContainerNode> m_node; 69 74 OwnPtr<ElementRecord> m_next; 70 75 }; … … 76 81 ASSERT(m_top->element()); 77 82 return m_top->element(); 83 } 84 85 ContainerNode* topNode() const 86 { 87 ASSERT(m_top->node()); 88 return m_top->node(); 78 89 } 79 90 … … 87 98 88 99 void push(PassRefPtr<Element>); 100 void pushRootNode(PassRefPtr<ContainerNode>); 89 101 void pushHTMLHtmlElement(PassRefPtr<Element>); 90 102 void pushHTMLHeadElement(PassRefPtr<Element>); … … 132 144 Element* headElement() const; 133 145 Element* bodyElement() const; 146 147 ContainerNode* rootNode() const; 134 148 135 149 #ifndef NDEBUG … … 138 152 139 153 private: 140 void pushCommon(PassRefPtr<Element>); 154 void pushCommon(PassRefPtr<ContainerNode>); 155 void pushRootNodeCommon(PassRefPtr<ContainerNode>); 141 156 void popCommon(); 142 157 void removeNonTopCommon(Element*); … … 144 159 OwnPtr<ElementRecord> m_top; 145 160 146 // We remember <html>, <head> and <body> as they are pushed.Their147 // ElementRecords keep them alive. <html>is never popped.161 // We remember the root node, <head> and <body> as they are pushed. Their 162 // ElementRecords keep them alive. The root node is never popped. 148 163 // FIXME: We don't currently require type-specific information about 149 164 // these elements so we haven't yet bothered to plumb the types all the 150 165 // way down through createElement, etc. 151 Element* m_htmlElement;166 ContainerNode* m_rootNode; 152 167 Element* m_headElement; 153 168 Element* m_bodyElement; -
trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
r79816 r80201 1 1 /* 2 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 122 123 || node->hasTagName(SVGNames::descTag) 123 124 || node->hasTagName(SVGNames::titleTag)) 125 return true; 126 if (node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) 124 127 return true; 125 128 if (node->namespaceURI() != xhtmlNamespaceURI) … … 376 379 // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm: 377 380 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case 378 processFakeStartTag(htmlTag); 381 // For efficiency, we skip step 4.2 ("Let root be a new html element with no attributes") 382 // and instead use the DocumentFragment as a root node. 383 m_tree.openElements()->pushRootNode(fragment); 379 384 resetInsertionModeAppropriately(); 380 385 m_tree.setForm(closestFormAncestor(contextElement)); … … 409 414 { 410 415 ASSERT(!fragment->hasChildNodes()); 411 }412 413 void HTMLTreeBuilder::FragmentParsingContext::finished()414 {415 if (!m_contextElement)416 return;417 418 // The HTML5 spec says to return the children of the fragment's document419 // element when there is a context element (10.4.7).420 RefPtr<ContainerNode> documentElement = firstElementChild(m_fragment);421 m_fragment->removeChildren();422 ASSERT(documentElement);423 m_fragment->takeAllChildrenFrom(documentElement.get());424 416 } 425 417 … … 575 567 namespace { 576 568 577 bool isLi(const Element* element)569 bool isLi(const ContainerNode* element) 578 570 { 579 571 return element->hasTagName(liTag); 580 572 } 581 573 582 bool isDdOrDt(const Element* element)574 bool isDdOrDt(const ContainerNode* element) 583 575 { 584 576 return element->hasTagName(ddTag) … … 588 580 } 589 581 590 template <bool shouldClose(const Element*)>582 template <bool shouldClose(const ContainerNode*)> 591 583 void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken& token) 592 584 { … … 594 586 HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord(); 595 587 while (1) { 596 Element* node = nodeRecord->element();588 ContainerNode* node = nodeRecord->node(); 597 589 if (shouldClose(node)) { 598 processFakeEndTag(node->tagQName()); 590 ASSERT(node->isElementNode()); 591 processFakeEndTag(toElement(node)->tagQName()); 599 592 break; 600 593 } … … 787 780 if (isNumberedHeaderTag(token.name())) { 788 781 processFakePEndTagIfPInButtonScope(); 789 if (isNumberedHeaderTag(m_tree.current Element()->localName())) {782 if (isNumberedHeaderTag(m_tree.currentNode()->localName())) { 790 783 parseError(token); 791 784 m_tree.openElements()->pop(); … … 979 972 if (m_tree.openElements()->inScope(rubyTag.localName())) { 980 973 m_tree.generateImpliedEndTags(); 981 if (!m_tree.current Element()->hasTagName(rubyTag)) {974 if (!m_tree.currentNode()->hasTagName(rubyTag)) { 982 975 parseError(token); 983 976 m_tree.openElements()->popUntil(rubyTag.localName()); … … 1020 1013 bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup() 1021 1014 { 1022 if (m_tree.current Element() == m_tree.openElements()->htmlElement()) {1015 if (m_tree.currentNode() == m_tree.openElements()->rootNode()) { 1023 1016 ASSERT(isParsingFragment()); 1024 1017 // FIXME: parse error … … 1116 1109 namespace { 1117 1110 1118 bool shouldProcessForeignContentUsingInBodyInsertionMode(AtomicHTMLToken& token, Element* currentElement)1111 bool shouldProcessForeignContentUsingInBodyInsertionMode(AtomicHTMLToken& token, ContainerNode* currentElement) 1119 1112 { 1120 1113 ASSERT(token.type() == HTMLToken::StartTag); … … 1410 1403 } 1411 1404 if (token.name() == optionTag) { 1412 if (m_tree.current Element()->hasTagName(optionTag)) {1405 if (m_tree.currentNode()->hasTagName(optionTag)) { 1413 1406 AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName()); 1414 1407 processEndTag(endOption); … … 1418 1411 } 1419 1412 if (token.name() == optgroupTag) { 1420 if (m_tree.current Element()->hasTagName(optionTag)) {1413 if (m_tree.currentNode()->hasTagName(optionTag)) { 1421 1414 AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName()); 1422 1415 processEndTag(endOption); 1423 1416 } 1424 if (m_tree.current Element()->hasTagName(optgroupTag)) {1417 if (m_tree.currentNode()->hasTagName(optgroupTag)) { 1425 1418 AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName()); 1426 1419 processEndTag(endOptgroup); … … 1544 1537 HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord(); 1545 1538 while (1) { 1546 Element* node = record->element();1539 ContainerNode* node = record->node(); 1547 1540 if (node->hasLocalName(token.name())) { 1548 1541 m_tree.generateImpliedEndTags(); 1549 if (!m_tree.current Element()->hasLocalName(token.name())) {1542 if (!m_tree.currentNode()->hasLocalName(token.name())) { 1550 1543 parseError(token); 1551 1544 // FIXME: This is either a bug in the spec, or a bug in our … … 1554 1547 // We might have already popped the node for the token in 1555 1548 // generateImpliedEndTags, just abort. 1556 if (!m_tree.openElements()->contains( node))1549 if (!m_tree.openElements()->contains(record->element())) 1557 1550 return; 1558 1551 } 1559 m_tree.openElements()->popUntilPopped( node);1552 m_tree.openElements()->popUntilPopped(record->element()); 1560 1553 return; 1561 1554 } … … 1617 1610 // 4. 1618 1611 ASSERT(furthestBlock->isAbove(formattingElementRecord)); 1619 Element* commonAncestor = formattingElementRecord->next()->element();1612 ContainerNode* commonAncestor = formattingElementRecord->next()->node(); 1620 1613 // 5. 1621 1614 HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement); … … 1669 1662 else { 1670 1663 commonAncestor->parserAddChild(lastNode->element()); 1671 if (lastNode->element()->parentElement()->attached() && !lastNode->element()->attached()) 1664 ASSERT(lastNode->node()->isElementNode()); 1665 ASSERT(lastNode->element()->parentNode()); 1666 if (lastNode->element()->parentNode()->attached() && !lastNode->element()->attached()) 1672 1667 lastNode->element()->lazyAttach(); 1673 1668 } … … 1701 1696 HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord(); 1702 1697 while (1) { 1703 Element* node = nodeRecord->element();1704 if (node == m_tree.openElements()-> bottom()) {1698 ContainerNode* node = nodeRecord->node(); 1699 if (node == m_tree.openElements()->rootNode()) { 1705 1700 ASSERT(isParsingFragment()); 1706 1701 last = true; … … 1832 1827 } 1833 1828 m_tree.generateImpliedEndTags(); 1834 if (!m_tree.current Element()->hasLocalName(token.name()))1829 if (!m_tree.currentNode()->hasLocalName(token.name())) 1835 1830 parseError(token); 1836 1831 m_tree.openElements()->popUntilPopped(token.name()); … … 1902 1897 } 1903 1898 m_tree.generateImpliedEndTags(); 1904 if (!m_tree.current Element()->hasLocalName(token.name()))1899 if (!m_tree.currentNode()->hasLocalName(token.name())) 1905 1900 parseError(token); 1906 1901 m_tree.openElements()->popUntilPopped(token.name()); … … 1927 1922 } 1928 1923 m_tree.generateImpliedEndTagsWithExclusion(token.name()); 1929 if (!m_tree.current Element()->hasLocalName(token.name()))1924 if (!m_tree.currentNode()->hasLocalName(token.name())) 1930 1925 parseError(token); 1931 1926 m_tree.openElements()->popUntilPopped(token.name()); … … 1938 1933 } 1939 1934 m_tree.generateImpliedEndTagsWithExclusion(token.name()); 1940 if (!m_tree.current Element()->hasLocalName(token.name()))1935 if (!m_tree.currentNode()->hasLocalName(token.name())) 1941 1936 parseError(token); 1942 1937 m_tree.openElements()->popUntilPopped(token.name()); … … 1950 1945 } 1951 1946 m_tree.generateImpliedEndTagsWithExclusion(token.name()); 1952 if (!m_tree.current Element()->hasLocalName(token.name()))1947 if (!m_tree.currentNode()->hasLocalName(token.name())) 1953 1948 parseError(token); 1954 1949 m_tree.openElements()->popUntilPopped(token.name()); … … 1961 1956 } 1962 1957 m_tree.generateImpliedEndTags(); 1963 if (!m_tree.current Element()->hasLocalName(token.name()))1958 if (!m_tree.currentNode()->hasLocalName(token.name())) 1964 1959 parseError(token); 1965 1960 m_tree.openElements()->popUntilNumberedHeaderElementPopped(); … … 1978 1973 } 1979 1974 m_tree.generateImpliedEndTags(); 1980 if (!m_tree.current Element()->hasLocalName(token.name()))1975 if (!m_tree.currentNode()->hasLocalName(token.name())) 1981 1976 parseError(token); 1982 1977 m_tree.openElements()->popUntilPopped(token.name()); … … 2222 2217 ASSERT(insertionMode() == InFramesetMode); 2223 2218 if (token.name() == framesetTag) { 2224 if (m_tree.current Element() == m_tree.openElements()->htmlElement()) {2219 if (m_tree.currentNode() == m_tree.openElements()->rootNode()) { 2225 2220 parseError(token); 2226 2221 return; … … 2262 2257 ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode); 2263 2258 if (token.name() == optgroupTag) { 2264 if (m_tree.current Element()->hasTagName(optionTag) && m_tree.oneBelowTop()->hasTagName(optgroupTag))2259 if (m_tree.currentNode()->hasTagName(optionTag) && m_tree.oneBelowTop()->hasTagName(optgroupTag)) 2265 2260 processFakeEndTag(optionTag); 2266 if (m_tree.current Element()->hasTagName(optgroupTag)) {2261 if (m_tree.currentNode()->hasTagName(optgroupTag)) { 2267 2262 m_tree.openElements()->pop(); 2268 2263 return; … … 2295 2290 break; 2296 2291 case InForeignContentMode: 2297 if (token.name() == SVGNames::scriptTag && m_tree.current Element()->hasTagName(SVGNames::scriptTag)) {2292 if (token.name() == SVGNames::scriptTag && m_tree.currentNode()->hasTagName(SVGNames::scriptTag)) { 2298 2293 notImplemented(); 2299 2294 return; 2300 2295 } 2301 if (m_tree.current Element()->namespaceURI() != xhtmlNamespaceURI) {2296 if (m_tree.currentNode()->namespaceURI() != xhtmlNamespaceURI) { 2302 2297 // FIXME: This code just wants an Element* iterator, instead of an ElementRecord* 2303 2298 HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord(); 2304 if (!nodeRecord-> element()->hasLocalName(token.name()))2299 if (!nodeRecord->node()->hasLocalName(token.name())) 2305 2300 parseError(token); 2306 2301 while (1) { 2307 if (nodeRecord-> element()->hasLocalName(token.name())) {2302 if (nodeRecord->node()->hasLocalName(token.name())) { 2308 2303 m_tree.openElements()->popUntilPopped(nodeRecord->element()); 2309 2304 resetForeignInsertionMode(); … … 2311 2306 } 2312 2307 nodeRecord = nodeRecord->next(); 2313 if (nodeRecord->element()->namespaceURI() == xhtmlNamespaceURI) 2308 2309 // Fragments containing only foreign content will not have a 2310 // node with the XHTML namespace URI, so we should stop walking 2311 // the element stack when we encounter the DocumentFragment itself. 2312 if (nodeRecord->node()->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) { 2313 ASSERT(isParsingFragment()); 2314 break; 2315 } 2316 2317 if (nodeRecord->node()->namespaceURI() == xhtmlNamespaceURI) 2314 2318 break; 2315 2319 } … … 2610 2614 case InSelectMode: 2611 2615 ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode || insertionMode() == InTableMode || insertionMode() == InFramesetMode || insertionMode() == InTableBodyMode); 2612 if (m_tree.current Element() != m_tree.openElements()->htmlElement())2616 if (m_tree.currentNode() != m_tree.openElements()->rootNode()) 2613 2617 parseError(token); 2614 2618 break; 2615 2619 case InColumnGroupMode: 2616 if (m_tree.current Element() == m_tree.openElements()->htmlElement()) {2620 if (m_tree.currentNode() == m_tree.openElements()->rootNode()) { 2617 2621 ASSERT(isParsingFragment()); 2618 2622 return; // FIXME: Should we break here instead of returning? … … 2643 2647 return; 2644 2648 } 2645 ASSERT(m_tree. openElements()->top());2649 ASSERT(m_tree.currentNode()); 2646 2650 m_tree.openElements()->popAll(); 2647 2651 } … … 2795 2799 void HTMLTreeBuilder::finished() 2796 2800 { 2801 if (isParsingFragment()) 2802 return; 2803 2797 2804 ASSERT(m_document); 2798 if (isParsingFragment()) {2799 m_fragmentContext.finished();2800 return;2801 }2802 2803 2805 // Warning, this may detach the parser. Do not do anything else after this. 2804 2806 m_document->finishedParsing(); -
trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h
r78286 r80201 1 1 /* 2 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without … … 179 180 void closeTheCell(); 180 181 181 template <bool shouldClose(const Element*)>182 template <bool shouldClose(const ContainerNode*)> 182 183 void processCloseWhenNestedTag(AtomicHTMLToken&); 183 184 … … 216 217 FragmentScriptingPermission scriptingPermission() const { ASSERT(m_fragment); return m_scriptingPermission; } 217 218 218 void finished();219 220 219 private: 221 220 DocumentFragment* m_fragment;
Note: See TracChangeset
for help on using the changeset viewer.