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