• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 blink {
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 
element()60         Element* element() const { return m_item->element(); }
node()61         ContainerNode* node() const { return m_item->node(); }
namespaceURI()62         const AtomicString& namespaceURI() const { return m_item->namespaceURI(); }
stackItem()63         PassRefPtrWillBeRawPtr<HTMLStackItem> stackItem() const { return m_item; }
64         void replaceElement(PassRefPtrWillBeRawPtr<HTMLStackItem>);
65 
66         bool isAbove(ElementRecord*) const;
67 
next()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 
releaseNext()76         PassOwnPtrWillBeRawPtr<ElementRecord> releaseNext() { return m_next.release(); }
setNext(PassOwnPtrWillBeRawPtr<ElementRecord> next)77         void setNext(PassOwnPtrWillBeRawPtr<ElementRecord> next) { m_next = next; }
78 
79         RefPtrWillBeMember<HTMLStackItem> m_item;
80         OwnPtrWillBeMember<ElementRecord> m_next;
81     };
82 
stackDepth()83     unsigned stackDepth() const { return m_stackDepth; }
84 
85     // Inlining this function is a (small) performance win on the parsing
86     // benchmark.
top()87     Element* top() const
88     {
89         ASSERT(m_top->element());
90         return m_top->element();
91     }
92 
topNode()93     ContainerNode* topNode() const
94     {
95         ASSERT(m_top->node());
96         return m_top->node();
97     }
98 
topStackItem()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);
popUntilPopped(const QualifiedName & 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 blink
193 
194 #endif // HTMLElementStack_h
195