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