1/* 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 3 * Copyright (C) 2011 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#ifndef HTMLElementStack_h 28#define HTMLElementStack_h 29 30#include "HTMLStackItem.h" 31#include <wtf/Forward.h> 32#include <wtf/Noncopyable.h> 33#include <wtf/RefPtr.h> 34 35namespace WebCore { 36 37class ContainerNode; 38class DocumentFragment; 39class Element; 40class QualifiedName; 41 42// NOTE: The HTML5 spec uses a backwards (grows downward) stack. We're using 43// more standard (grows upwards) stack terminology here. 44class HTMLElementStack { 45 WTF_MAKE_NONCOPYABLE(HTMLElementStack); WTF_MAKE_FAST_ALLOCATED; 46public: 47 HTMLElementStack(); 48 ~HTMLElementStack(); 49 50 class ElementRecord { 51 WTF_MAKE_NONCOPYABLE(ElementRecord); WTF_MAKE_FAST_ALLOCATED; 52 public: 53 ElementRecord(PassRefPtr<HTMLStackItem>, std::unique_ptr<ElementRecord>); 54 ~ElementRecord(); 55 56 Element* element() const { return m_item->element(); } 57 ContainerNode* node() const { return m_item->node(); } 58 const AtomicString& namespaceURI() const { return m_item->namespaceURI(); } 59 PassRefPtr<HTMLStackItem> stackItem() const { return m_item; } 60 void replaceElement(PassRefPtr<HTMLStackItem>); 61 62 bool isAbove(ElementRecord*) const; 63 64 ElementRecord* next() const { return m_next.get(); } 65 private: 66 friend class HTMLElementStack; 67 68 std::unique_ptr<ElementRecord> releaseNext() { return WTF::move(m_next); } 69 void setNext(std::unique_ptr<ElementRecord> next) { m_next = WTF::move(next); } 70 71 RefPtr<HTMLStackItem> m_item; 72 std::unique_ptr<ElementRecord> m_next; 73 }; 74 75 unsigned stackDepth() const { return m_stackDepth; } 76 77 // Inlining this function is a (small) performance win on the parsing 78 // benchmark. 79 Element* top() const 80 { 81 ASSERT(m_top->element()); 82 return m_top->element(); 83 } 84 85 ContainerNode* topNode() const 86 { 87 ASSERT(m_top->node()); 88 return m_top->node(); 89 } 90 91 HTMLStackItem* topStackItem() const 92 { 93 ASSERT(m_top->stackItem()); 94 return m_top->stackItem().get(); 95 } 96 97 HTMLStackItem* oneBelowTop() const; 98 ElementRecord* topRecord() const; 99 ElementRecord* find(Element*) const; 100 ElementRecord* furthestBlockForFormattingElement(Element*) const; 101 ElementRecord* topmost(const AtomicString& tagName) const; 102 103 void insertAbove(PassRefPtr<HTMLStackItem>, ElementRecord*); 104 105 void push(PassRefPtr<HTMLStackItem>); 106 void pushRootNode(PassRefPtr<HTMLStackItem>); 107 void pushHTMLHtmlElement(PassRefPtr<HTMLStackItem>); 108 void pushHTMLHeadElement(PassRefPtr<HTMLStackItem>); 109 void pushHTMLBodyElement(PassRefPtr<HTMLStackItem>); 110 111 void pop(); 112 void popUntil(const AtomicString& tagName); 113 void popUntil(Element*); 114 void popUntilPopped(const AtomicString& tagName); 115 void popUntilPopped(const QualifiedName& tagName) { popUntilPopped(tagName.localName()); } 116 117 void popUntilPopped(Element*); 118 void popUntilNumberedHeaderElementPopped(); 119 void popUntilTableScopeMarker(); // "clear the stack back to a table context" in the spec. 120 void popUntilTableBodyScopeMarker(); // "clear the stack back to a table body context" in the spec. 121 void popUntilTableRowScopeMarker(); // "clear the stack back to a table row context" in the spec. 122 void popUntilForeignContentScopeMarker(); 123 void popHTMLHeadElement(); 124 void popHTMLBodyElement(); 125 void popAll(); 126 127 static bool isMathMLTextIntegrationPoint(HTMLStackItem*); 128 static bool isHTMLIntegrationPoint(HTMLStackItem*); 129 130 void remove(Element*); 131 void removeHTMLHeadElement(Element*); 132 133 bool contains(Element*) const; 134 bool contains(const AtomicString& tagName) const; 135 136 bool inScope(Element*) const; 137 bool inScope(const AtomicString& tagName) const; 138 bool inScope(const QualifiedName&) const; 139 bool inListItemScope(const AtomicString& tagName) const; 140 bool inListItemScope(const QualifiedName&) const; 141 bool inTableScope(const AtomicString& tagName) const; 142 bool inTableScope(const QualifiedName&) const; 143 bool inButtonScope(const AtomicString& tagName) const; 144 bool inButtonScope(const QualifiedName&) const; 145 bool inSelectScope(const AtomicString& tagName) const; 146 bool inSelectScope(const QualifiedName&) const; 147 148 bool hasNumberedHeaderElementInScope() const; 149 150 bool hasOnlyOneElement() const; 151 bool secondElementIsHTMLBodyElement() const; 152#if ENABLE(TEMPLATE_ELEMENT) 153 bool hasTemplateInHTMLScope() const; 154#endif 155 Element* htmlElement() const; 156 Element* headElement() const; 157 Element* bodyElement() const; 158 159 ContainerNode* rootNode() const; 160 161#ifndef NDEBUG 162 void show(); 163#endif 164 165private: 166 void pushCommon(PassRefPtr<HTMLStackItem>); 167 void pushRootNodeCommon(PassRefPtr<HTMLStackItem>); 168 void popCommon(); 169 void removeNonTopCommon(Element*); 170 171 std::unique_ptr<ElementRecord> m_top; 172 173 // We remember the root node, <head> and <body> as they are pushed. Their 174 // ElementRecords keep them alive. The root node is never popped. 175 // FIXME: We don't currently require type-specific information about 176 // these elements so we haven't yet bothered to plumb the types all the 177 // way down through createElement, etc. 178 ContainerNode* m_rootNode; 179 Element* m_headElement; 180 Element* m_bodyElement; 181 unsigned m_stackDepth; 182}; 183 184} // namespace WebCore 185 186#endif // HTMLElementStack_h 187