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 "core/html/parser/HTMLStackItem.h" 31 #include "wtf/Forward.h" 32 #include "wtf/Noncopyable.h" 33 #include "wtf/OwnPtr.h" 34 #include "wtf/PassOwnPtr.h" 35 #include "wtf/RefPtr.h" 36 37 namespace WebCore { 38 39 class ContainerNode; 40 class DocumentFragment; 41 class Element; 42 class QualifiedName; 43 44 // NOTE: The HTML5 spec uses a backwards (grows downward) stack. We're using 45 // more standard (grows upwards) stack terminology here. 46 class HTMLElementStack { 47 WTF_MAKE_NONCOPYABLE(HTMLElementStack); WTF_MAKE_FAST_ALLOCATED; 48 public: 49 HTMLElementStack(); 50 ~HTMLElementStack(); 51 52 class ElementRecord { 53 WTF_MAKE_NONCOPYABLE(ElementRecord); WTF_MAKE_FAST_ALLOCATED; 54 public: 55 ~ElementRecord(); // Public for ~PassOwnPtr() 56 57 Element* element() const { return m_item->element(); } 58 ContainerNode* node() const { return m_item->node(); } 59 const AtomicString& namespaceURI() const { return m_item->namespaceURI(); } 60 PassRefPtr<HTMLStackItem> stackItem() const { return m_item; } 61 void replaceElement(PassRefPtr<HTMLStackItem>); 62 63 bool isAbove(ElementRecord*) const; 64 65 ElementRecord* next() const { return m_next.get(); } 66 private: 67 friend class HTMLElementStack; 68 69 ElementRecord(PassRefPtr<HTMLStackItem>, PassOwnPtr<ElementRecord>); 70 71 PassOwnPtr<ElementRecord> releaseNext() { return m_next.release(); } 72 void setNext(PassOwnPtr<ElementRecord> next) { m_next = next; } 73 74 RefPtr<HTMLStackItem> m_item; 75 OwnPtr<ElementRecord> m_next; 76 }; 77 78 unsigned stackDepth() const { return m_stackDepth; } 79 80 // Inlining this function is a (small) performance win on the parsing 81 // benchmark. 82 Element* top() const 83 { 84 ASSERT(m_top->element()); 85 return m_top->element(); 86 } 87 88 ContainerNode* topNode() const 89 { 90 ASSERT(m_top->node()); 91 return m_top->node(); 92 } 93 94 HTMLStackItem* topStackItem() const 95 { 96 ASSERT(m_top->stackItem()); 97 return m_top->stackItem().get(); 98 } 99 100 HTMLStackItem* oneBelowTop() const; 101 ElementRecord* topRecord() const; 102 ElementRecord* find(Element*) const; 103 ElementRecord* furthestBlockForFormattingElement(Element*) const; 104 ElementRecord* topmost(const AtomicString& tagName) const; 105 106 void insertAbove(PassRefPtr<HTMLStackItem>, ElementRecord*); 107 108 void push(PassRefPtr<HTMLStackItem>); 109 void pushRootNode(PassRefPtr<HTMLStackItem>); 110 void pushHTMLHtmlElement(PassRefPtr<HTMLStackItem>); 111 void pushHTMLHeadElement(PassRefPtr<HTMLStackItem>); 112 void pushHTMLBodyElement(PassRefPtr<HTMLStackItem>); 113 114 void pop(); 115 void popUntil(const AtomicString& tagName); 116 void popUntil(Element*); 117 void popUntilPopped(const AtomicString& tagName); 118 void popUntilPopped(const QualifiedName& tagName) { popUntilPopped(tagName.localName()); } 119 120 void popUntilPopped(Element*); 121 void popUntilNumberedHeaderElementPopped(); 122 void popUntilTableScopeMarker(); // "clear the stack back to a table context" in the spec. 123 void popUntilTableBodyScopeMarker(); // "clear the stack back to a table body context" in the spec. 124 void popUntilTableRowScopeMarker(); // "clear the stack back to a table row context" in the spec. 125 void popUntilForeignContentScopeMarker(); 126 void popHTMLHeadElement(); 127 void popHTMLBodyElement(); 128 void popAll(); 129 130 static bool isMathMLTextIntegrationPoint(HTMLStackItem*); 131 static bool isHTMLIntegrationPoint(HTMLStackItem*); 132 133 void remove(Element*); 134 void removeHTMLHeadElement(Element*); 135 136 bool contains(Element*) const; 137 bool contains(const AtomicString& tagName) const; 138 139 bool inScope(Element*) const; 140 bool inScope(const AtomicString& tagName) const; 141 bool inScope(const QualifiedName&) const; 142 bool inListItemScope(const AtomicString& tagName) const; 143 bool inListItemScope(const QualifiedName&) const; 144 bool inTableScope(const AtomicString& tagName) const; 145 bool inTableScope(const QualifiedName&) const; 146 bool inButtonScope(const AtomicString& tagName) const; 147 bool inButtonScope(const QualifiedName&) const; 148 bool inSelectScope(const AtomicString& tagName) const; 149 bool inSelectScope(const QualifiedName&) const; 150 151 bool hasNumberedHeaderElementInScope() const; 152 153 bool hasOnlyOneElement() const; 154 bool secondElementIsHTMLBodyElement() const; 155 bool hasTemplateInHTMLScope() const; 156 Element* htmlElement() const; 157 Element* headElement() const; 158 Element* bodyElement() const; 159 160 ContainerNode* rootNode() const; 161 162 #ifndef NDEBUG 163 void show(); 164 #endif 165 166 private: 167 void pushCommon(PassRefPtr<HTMLStackItem>); 168 void pushRootNodeCommon(PassRefPtr<HTMLStackItem>); 169 void popCommon(); 170 void removeNonTopCommon(Element*); 171 172 OwnPtr<ElementRecord> m_top; 173 174 // We remember the root node, <head> and <body> as they are pushed. Their 175 // ElementRecords keep them alive. The root node is never popped. 176 // FIXME: We don't currently require type-specific information about 177 // these elements so we haven't yet bothered to plumb the types all the 178 // way down through createElement, etc. 179 ContainerNode* m_rootNode; 180 Element* m_headElement; 181 Element* m_bodyElement; 182 unsigned m_stackDepth; 183 }; 184 185 } // namespace WebCore 186 187 #endif // HTMLElementStack_h 188