Home | History | Annotate | Download | only in parser
      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 
     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 blink
    193 
    194 #endif // HTMLElementStack_h
    195