Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Peter Kelly (pmk (at) post.com)
      5  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      6  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  *
     23  */
     24 
     25 #ifndef Element_h
     26 #define Element_h
     27 
     28 #include "CSSPropertyNames.h"
     29 #include "HTMLNames.h"
     30 #include "core/css/CSSPrimitiveValue.h"
     31 #include "core/dom/Attribute.h"
     32 #include "core/dom/Document.h"
     33 #include "core/dom/SpaceSplitString.h"
     34 #include "core/html/CollectionType.h"
     35 #include "core/page/FocusDirection.h"
     36 #include "core/platform/ScrollTypes.h"
     37 #include "core/rendering/RegionOversetState.h"
     38 
     39 namespace WebCore {
     40 
     41 class ActiveAnimations;
     42 class Attr;
     43 class Attribute;
     44 class ClientRect;
     45 class ClientRectList;
     46 class DOMStringMap;
     47 class DOMTokenList;
     48 class Element;
     49 class ElementRareData;
     50 class ElementShadow;
     51 class ExceptionState;
     52 class Image;
     53 class InputMethodContext;
     54 class IntSize;
     55 class Locale;
     56 class MutableStylePropertySet;
     57 class PropertySetCSSStyleDeclaration;
     58 class PseudoElement;
     59 class RenderRegion;
     60 class ShadowRoot;
     61 class ShareableElementData;
     62 class StylePropertySet;
     63 class UniqueElementData;
     64 
     65 struct PresentationAttributeCacheKey;
     66 
     67 class ElementData : public RefCounted<ElementData> {
     68     WTF_MAKE_FAST_ALLOCATED;
     69 public:
     70     // Override RefCounted's deref() to ensure operator delete is called on
     71     // the appropriate subclass type.
     72     void deref();
     73 
     74     void clearClass() const { m_classNames.clear(); }
     75     void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
     76     const SpaceSplitString& classNames() const { return m_classNames; }
     77 
     78     const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
     79     void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
     80 
     81     const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
     82 
     83     const StylePropertySet* presentationAttributeStyle() const;
     84 
     85     size_t length() const;
     86     bool isEmpty() const { return !length(); }
     87 
     88     const Attribute* attributeItem(unsigned index) const;
     89     const Attribute* getAttributeItem(const QualifiedName&) const;
     90     size_t getAttributeItemIndex(const QualifiedName&) const;
     91     size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
     92     size_t getAttrIndex(Attr*) const;
     93 
     94     bool hasID() const { return !m_idForStyleResolution.isNull(); }
     95     bool hasClass() const { return !m_classNames.isNull(); }
     96 
     97     bool isEquivalent(const ElementData* other) const;
     98 
     99     bool isUnique() const { return m_isUnique; }
    100 
    101 protected:
    102     ElementData();
    103     ElementData(unsigned arraySize);
    104     ElementData(const ElementData&, bool isUnique);
    105 
    106     unsigned m_isUnique : 1;
    107     unsigned m_arraySize : 28;
    108     mutable unsigned m_presentationAttributeStyleIsDirty : 1;
    109     mutable unsigned m_styleAttributeIsDirty : 1;
    110     mutable unsigned m_animatedSVGAttributesAreDirty : 1;
    111 
    112     mutable RefPtr<StylePropertySet> m_inlineStyle;
    113     mutable SpaceSplitString m_classNames;
    114     mutable AtomicString m_idForStyleResolution;
    115 
    116 private:
    117     friend class Element;
    118     friend class ShareableElementData;
    119     friend class UniqueElementData;
    120     friend class SVGElement;
    121 
    122     const Attribute* attributeBase() const;
    123     const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    124     size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    125 
    126     PassRefPtr<UniqueElementData> makeUniqueCopy() const;
    127 };
    128 
    129 #if COMPILER(MSVC)
    130 #pragma warning(push)
    131 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
    132 #endif
    133 
    134 class ShareableElementData : public ElementData {
    135 public:
    136     static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
    137 
    138     explicit ShareableElementData(const Vector<Attribute>&);
    139     explicit ShareableElementData(const UniqueElementData&);
    140     ~ShareableElementData();
    141 
    142     Attribute m_attributeArray[0];
    143 };
    144 
    145 #if COMPILER(MSVC)
    146 #pragma warning(pop)
    147 #endif
    148 
    149 class UniqueElementData : public ElementData {
    150 public:
    151     static PassRefPtr<UniqueElementData> create();
    152     PassRefPtr<ShareableElementData> makeShareableCopy() const;
    153 
    154     // These functions do no error/duplicate checking.
    155     void addAttribute(const QualifiedName&, const AtomicString&);
    156     void removeAttribute(size_t index);
    157 
    158     Attribute* attributeItem(unsigned index);
    159     Attribute* getAttributeItem(const QualifiedName&);
    160 
    161     UniqueElementData();
    162     explicit UniqueElementData(const ShareableElementData&);
    163     explicit UniqueElementData(const UniqueElementData&);
    164 
    165     mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
    166     Vector<Attribute, 4> m_attributeVector;
    167 };
    168 
    169 enum AffectedSelectorType {
    170     AffectedSelectorChecked = 1,
    171     AffectedSelectorEnabled = 1 << 1,
    172     AffectedSelectorDisabled = 1 << 2,
    173     AffectedSelectorIndeterminate = 1 << 3,
    174     AffectedSelectorLink = 1 << 4,
    175     AffectedSelectorTarget = 1 << 5,
    176     AffectedSelectorVisited = 1 << 6
    177 };
    178 typedef int AffectedSelectorMask;
    179 
    180 enum SpellcheckAttributeState {
    181     SpellcheckAttributeTrue,
    182     SpellcheckAttributeFalse,
    183     SpellcheckAttributeDefault
    184 };
    185 
    186 class Element : public ContainerNode {
    187 public:
    188     static PassRefPtr<Element> create(const QualifiedName&, Document*);
    189     virtual ~Element();
    190 
    191     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
    192     DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
    193     DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
    194     DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
    195     DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
    196     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
    197     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
    198     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
    199     DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
    200     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
    201     DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
    202     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
    203     DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
    204     DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
    205     DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
    206     DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
    207     DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
    208     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
    209     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseenter);
    210     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseleave);
    211     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
    212     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
    213     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
    214     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
    215     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
    216     DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
    217     DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
    218     DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
    219 
    220     // These four attribute event handler attributes are overridden by HTMLBodyElement
    221     // and HTMLFrameSetElement to forward to the DOMWindow.
    222     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
    223     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
    224     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
    225     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
    226 
    227     // WebKit extensions
    228     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
    229     DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
    230     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
    231     DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
    232     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
    233     DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
    234     DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
    235     DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
    236     DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
    237     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
    238     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
    239     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
    240     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
    241     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
    242     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
    243 
    244     bool hasAttribute(const QualifiedName&) const;
    245     const AtomicString& getAttribute(const QualifiedName&) const;
    246     void setAttribute(const QualifiedName&, const AtomicString& value);
    247     void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
    248     void removeAttribute(const QualifiedName&);
    249 
    250     // Typed getters and setters for language bindings.
    251     int getIntegralAttribute(const QualifiedName& attributeName) const;
    252     void setIntegralAttribute(const QualifiedName& attributeName, int value);
    253     unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
    254     void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
    255 
    256     // Call this to get the value of an attribute that is known not to be the style
    257     // attribute or one of the SVG animatable attributes.
    258     bool fastHasAttribute(const QualifiedName&) const;
    259     const AtomicString& fastGetAttribute(const QualifiedName&) const;
    260 #ifndef NDEBUG
    261     bool fastAttributeLookupAllowed(const QualifiedName&) const;
    262 #endif
    263 
    264 #ifdef DUMP_NODE_STATISTICS
    265     bool hasNamedNodeMap() const;
    266 #endif
    267     bool hasAttributes() const;
    268     // This variant will not update the potentially invalid attributes. To be used when not interested
    269     // in style attribute or one of the SVG animation attributes.
    270     bool hasAttributesWithoutUpdate() const;
    271 
    272     bool hasAttribute(const AtomicString& name) const;
    273     bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
    274 
    275     const AtomicString& getAttribute(const AtomicString& name) const;
    276     const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const;
    277 
    278     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionState&);
    279     static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState&);
    280     void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionState&);
    281 
    282     bool isIdAttributeName(const QualifiedName&) const;
    283     const AtomicString& getIdAttribute() const;
    284     void setIdAttribute(const AtomicString&);
    285 
    286     const AtomicString& getNameAttribute() const;
    287     const AtomicString& getClassAttribute() const;
    288 
    289     // Call this to get the value of the id attribute for style resolution purposes.
    290     // The value will already be lowercased if the document is in compatibility mode,
    291     // so this function is not suitable for non-style uses.
    292     const AtomicString& idForStyleResolution() const;
    293 
    294     // Internal methods that assume the existence of attribute storage, one should use hasAttributes()
    295     // before calling them.
    296     size_t attributeCount() const;
    297     const Attribute* attributeItem(unsigned index) const;
    298     const Attribute* getAttributeItem(const QualifiedName&) const;
    299     size_t getAttributeItemIndex(const QualifiedName& name) const { return elementData()->getAttributeItemIndex(name); }
    300     size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); }
    301 
    302     void scrollIntoView(bool alignToTop = true);
    303     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
    304 
    305     void scrollByLines(int lines);
    306     void scrollByPages(int pages);
    307 
    308     int offsetLeft();
    309     int offsetTop();
    310     int offsetWidth();
    311     int offsetHeight();
    312 
    313     // FIXME: Replace uses of offsetParent in the platform with calls
    314     // to the render layer and merge bindingsOffsetParent and offsetParent.
    315     Element* bindingsOffsetParent();
    316 
    317     Element* offsetParent();
    318     int clientLeft();
    319     int clientTop();
    320     int clientWidth();
    321     int clientHeight();
    322     virtual int scrollLeft();
    323     virtual int scrollTop();
    324     virtual void setScrollLeft(int);
    325     virtual void setScrollTop(int);
    326     virtual int scrollWidth();
    327     virtual int scrollHeight();
    328 
    329     IntRect boundsInRootViewSpace();
    330 
    331     PassRefPtr<ClientRectList> getClientRects();
    332     PassRefPtr<ClientRect> getBoundingClientRect();
    333 
    334     // Returns the absolute bounding box translated into screen coordinates:
    335     IntRect screenRect() const;
    336 
    337     virtual void didMoveToNewDocument(Document*) OVERRIDE;
    338 
    339     void removeAttribute(const AtomicString& name);
    340     void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName);
    341 
    342     PassRefPtr<Attr> detachAttribute(size_t index);
    343 
    344     PassRefPtr<Attr> getAttributeNode(const AtomicString& name);
    345     PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName);
    346     PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionState&);
    347     PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionState&);
    348     PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionState&);
    349 
    350     PassRefPtr<Attr> attrIfExists(const QualifiedName&);
    351     PassRefPtr<Attr> ensureAttr(const QualifiedName&);
    352 
    353     const Vector<RefPtr<Attr> >& attrNodeList();
    354 
    355     CSSStyleDeclaration* style();
    356 
    357     const QualifiedName& tagQName() const { return m_tagName; }
    358     String tagName() const { return nodeName(); }
    359     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
    360 
    361     // A fast function for checking the local name against another atomic string.
    362     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
    363     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
    364 
    365     virtual const AtomicString& localName() const OVERRIDE { return m_tagName.localName(); }
    366     virtual const AtomicString& prefix() const OVERRIDE { return m_tagName.prefix(); }
    367     virtual const AtomicString& namespaceURI() const OVERRIDE { return m_tagName.namespaceURI(); }
    368 
    369     virtual KURL baseURI() const OVERRIDE FINAL;
    370 
    371     virtual String nodeName() const;
    372 
    373     PassRefPtr<Element> cloneElementWithChildren();
    374     PassRefPtr<Element> cloneElementWithoutChildren();
    375 
    376     void scheduleLayerUpdate();
    377 
    378     void normalizeAttributes();
    379     String nodeNamePreservingCase() const;
    380 
    381     void setBooleanAttribute(const QualifiedName& name, bool);
    382 
    383     virtual const StylePropertySet* additionalPresentationAttributeStyle() { return 0; }
    384     void invalidateStyleAttribute();
    385 
    386     const StylePropertySet* inlineStyle() const { return elementData() ? elementData()->m_inlineStyle.get() : 0; }
    387 
    388     bool setInlineStyleProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
    389     bool setInlineStyleProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
    390     bool setInlineStyleProperty(CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes, bool important = false);
    391     bool setInlineStyleProperty(CSSPropertyID, const String& value, bool important = false);
    392     bool removeInlineStyleProperty(CSSPropertyID);
    393     void removeAllInlineStyleProperties();
    394 
    395     void synchronizeStyleAttributeInternal() const;
    396 
    397     const StylePropertySet* presentationAttributeStyle();
    398     virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) { }
    399 
    400     // For exposing to DOM only.
    401     NamedNodeMap* attributes() const;
    402 
    403     enum AttributeModificationReason {
    404         ModifiedDirectly,
    405         ModifiedByCloning
    406     };
    407 
    408     // This method is called whenever an attribute is added, changed or removed.
    409     virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly);
    410     virtual void parseAttribute(const QualifiedName&, const AtomicString&) { }
    411 
    412     // Only called by the parser immediately after element construction.
    413     void parserSetAttributes(const Vector<Attribute>&);
    414 
    415     // Remove attributes that might introduce scripting from the vector leaving the element unchanged.
    416     void stripScriptingAttributes(Vector<Attribute>&) const;
    417 
    418     const ElementData* elementData() const { return m_elementData.get(); }
    419     UniqueElementData* ensureUniqueElementData();
    420 
    421     void synchronizeAllAttributes() const;
    422 
    423     // Clones attributes only.
    424     void cloneAttributesFromElement(const Element&);
    425 
    426     // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
    427     void cloneDataFromElement(const Element&);
    428 
    429     bool hasEquivalentAttributes(const Element* other) const;
    430 
    431     virtual void copyNonAttributePropertiesFromElement(const Element&) { }
    432 
    433     virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
    434     virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
    435     virtual RenderObject* createRenderer(RenderStyle*);
    436     virtual bool rendererIsNeeded(const NodeRenderingContext&);
    437     bool recalcStyle(StyleChange = NoChange);
    438     void didAffectSelector(AffectedSelectorMask);
    439 
    440     ElementShadow* shadow() const;
    441     ElementShadow* ensureShadow();
    442     PassRefPtr<ShadowRoot> createShadowRoot(ExceptionState&);
    443     ShadowRoot* shadowRoot() const;
    444 
    445     bool hasAuthorShadowRoot() const { return shadowRoot(); }
    446 
    447     ShadowRoot* userAgentShadowRoot() const;
    448     ShadowRoot* ensureUserAgentShadowRoot();
    449     Element* uaShadowElementById(const AtomicString& id) const;
    450     virtual bool supportsShadowElementForUserAgentShadow() const;
    451     virtual const AtomicString& shadowPseudoId() const { return !part().isEmpty() ? part() : pseudo(); }
    452 
    453     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
    454 
    455     // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.)
    456     bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); }
    457     bool childrenAffectedByHover() const { return hasRareData() && rareDataChildrenAffectedByHover(); }
    458     bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); }
    459     bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); }
    460     bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); }
    461     bool childrenAffectedByFirstChildRules() const { return hasRareData() && rareDataChildrenAffectedByFirstChildRules(); }
    462     bool childrenAffectedByLastChildRules() const { return hasRareData() && rareDataChildrenAffectedByLastChildRules(); }
    463     bool childrenAffectedByDirectAdjacentRules() const { return hasRareData() && rareDataChildrenAffectedByDirectAdjacentRules(); }
    464     bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); }
    465     bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); }
    466     unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; }
    467 
    468     bool hasFlagsSetDuringStylingOfChildren() const;
    469 
    470     void setStyleAffectedByEmpty();
    471     void setChildrenAffectedByHover(bool);
    472     void setChildrenAffectedByActive(bool);
    473     void setChildrenAffectedByDrag(bool);
    474     void setChildrenAffectedByFirstChildRules();
    475     void setChildrenAffectedByLastChildRules();
    476     void setChildrenAffectedByDirectAdjacentRules();
    477     void setChildrenAffectedByForwardPositionalRules();
    478     void setChildrenAffectedByBackwardPositionalRules();
    479     void setChildIndex(unsigned);
    480 
    481     void setIsInCanvasSubtree(bool);
    482     bool isInCanvasSubtree() const;
    483 
    484     bool isUpgradedCustomElement() { return customElementState() == Upgraded; }
    485     bool isUnresolvedCustomElement() { return isCustomElement() && !isUpgradedCustomElement(); }
    486 
    487     void setIsInsideRegion(bool);
    488     bool isInsideRegion() const;
    489 
    490     void setRegionOversetState(RegionOversetState);
    491     RegionOversetState regionOversetState() const;
    492 
    493     AtomicString computeInheritedLanguage() const;
    494     Locale& locale() const;
    495 
    496     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
    497 
    498     virtual bool isURLAttribute(const Attribute&) const { return false; }
    499     virtual bool isHTMLContentAttribute(const Attribute&) const { return false; }
    500 
    501     KURL getURLAttribute(const QualifiedName&) const;
    502     KURL getNonEmptyURLAttribute(const QualifiedName&) const;
    503 
    504     virtual const AtomicString& imageSourceURL() const;
    505     virtual String target() const { return String(); }
    506     virtual Image* imageContents() { return 0; }
    507 
    508     virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone);
    509     virtual void updateFocusAppearance(bool restorePreviousSelection);
    510     virtual void blur();
    511     // Whether this element can receive focus at all. Most elements are not
    512     // focusable but some elements, such as form controls and links, are. Unlike
    513     // rendererIsFocusable(), this method may be called when layout is not up to
    514     // date, so it must not use the renderer to determine focusability.
    515     virtual bool supportsFocus() const;
    516     // Whether the node can actually be focused.
    517     bool isFocusable() const;
    518     virtual bool isKeyboardFocusable() const;
    519     virtual bool isMouseFocusable() const;
    520     virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection);
    521     virtual void dispatchBlurEvent(Element* newFocusedElement);
    522     void dispatchFocusInEvent(const AtomicString& eventType, Element* oldFocusedElement);
    523     void dispatchFocusOutEvent(const AtomicString& eventType, Element* newFocusedElement);
    524 
    525     String innerText();
    526     String outerText();
    527 
    528     String textFromChildren();
    529 
    530     virtual String title() const { return String(); }
    531 
    532     const AtomicString& pseudo() const;
    533     virtual const AtomicString& part() const;
    534     void setPart(const AtomicString&);
    535 
    536     LayoutSize minimumSizeForResizing() const;
    537     void setMinimumSizeForResizing(const LayoutSize&);
    538 
    539     virtual void didBecomeFullscreenElement() { }
    540     virtual void willStopBeingFullscreenElement() { }
    541 
    542     bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
    543     virtual void finishParsingChildren();
    544     virtual void beginParsingChildren() OVERRIDE FINAL;
    545 
    546     PseudoElement* pseudoElement(PseudoId) const;
    547     RenderObject* pseudoElementRenderer(PseudoId) const;
    548 
    549     virtual bool matchesReadOnlyPseudoClass() const { return false; }
    550     virtual bool matchesReadWritePseudoClass() const { return false; }
    551     bool webkitMatchesSelector(const String& selectors, ExceptionState&);
    552     virtual bool shouldAppearIndeterminate() const { return false; }
    553 
    554     DOMTokenList* classList();
    555 
    556     DOMStringMap* dataset();
    557 
    558     static bool isMathMLElement() { return false; }
    559     virtual bool isMediaElement() const { return false; }
    560 
    561 #if ENABLE(INPUT_SPEECH)
    562     virtual bool isInputFieldSpeechButtonElement() const { return false; }
    563 #endif
    564 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    565     virtual bool isDateTimeEditElement() const { return false; }
    566     virtual bool isDateTimeFieldElement() const { return false; }
    567     virtual bool isPickerIndicatorElement() const { return false; }
    568 #endif
    569 
    570     virtual bool isFormControlElement() const { return false; }
    571     virtual bool isSpinButtonElement() const { return false; }
    572     virtual bool isTextFormControl() const { return false; }
    573     virtual bool isOptionalFormControl() const { return false; }
    574     virtual bool isRequiredFormControl() const { return false; }
    575     virtual bool isDefaultButtonForForm() const { return false; }
    576     virtual bool willValidate() const { return false; }
    577     virtual bool isValidFormControlElement() { return false; }
    578     virtual bool isInRange() const { return false; }
    579     virtual bool isOutOfRange() const { return false; }
    580     virtual bool isFrameElementBase() const { return false; }
    581     virtual bool isPasswordGeneratorButtonElement() const { return false; }
    582     virtual bool isClearButtonElement() const { return false; }
    583 
    584     virtual bool canContainRangeEndPoint() const { return true; }
    585 
    586     virtual const AtomicString& formControlType() const { return nullAtom; }
    587 
    588     // FIXME: Only HTMLInputElement uses these, they don't need to be virtual.
    589     virtual bool wasChangedSinceLastFormControlChangeEvent() const { return false; }
    590     virtual void setChangedSinceLastFormControlChangeEvent(bool) { }
    591     virtual void dispatchFormControlChangeEvent() { }
    592 
    593     // Used for disabled form elements; if true, prevents mouse events from being dispatched
    594     // to event listeners, and prevents DOMActivate events from being sent at all.
    595     virtual bool isDisabledFormControl() const { return false; }
    596 
    597     bool isInert() const;
    598     virtual bool shouldBeReparentedUnderRenderView(const RenderStyle*) const { return isInTopLayer(); }
    599 
    600     virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const;
    601     bool hasPendingResources() const;
    602     void setHasPendingResources();
    603     void clearHasPendingResources();
    604     virtual void buildPendingResource() { };
    605 
    606     enum {
    607         ALLOW_KEYBOARD_INPUT = 1 << 0,
    608         LEGACY_MOZILLA_REQUEST = 1 << 1,
    609     };
    610 
    611     void webkitRequestFullScreen(unsigned short flags);
    612     bool containsFullScreenElement() const;
    613     void setContainsFullScreenElement(bool);
    614     void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
    615 
    616     // W3C API
    617     void webkitRequestFullscreen();
    618 
    619     bool isInTopLayer() const;
    620     void setIsInTopLayer(bool);
    621 
    622     void webkitRequestPointerLock();
    623 
    624     bool isSpellCheckingEnabled() const;
    625 
    626     PassRefPtr<RenderStyle> styleForRenderer();
    627     PassRefPtr<RenderStyle> originalStyleForRenderer();
    628 
    629     RenderRegion* renderRegion() const;
    630     virtual bool shouldMoveToFlowThread(RenderStyle*) const;
    631     const AtomicString& webkitRegionOverset() const;
    632     Vector<RefPtr<Range> > webkitGetRegionFlowRanges() const;
    633 
    634     bool hasID() const;
    635     bool hasClass() const;
    636     const SpaceSplitString& classNames() const;
    637 
    638     IntSize savedLayerScrollOffset() const;
    639     void setSavedLayerScrollOffset(const IntSize&);
    640 
    641     ActiveAnimations* activeAnimations() const;
    642     ActiveAnimations* ensureActiveAnimations();
    643     bool hasActiveAnimations() const;
    644 
    645     InputMethodContext* inputMethodContext();
    646 
    647 protected:
    648     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
    649         : ContainerNode(document, type)
    650         , m_tagName(tagName)
    651     {
    652         ScriptWrappable::init(this);
    653     }
    654 
    655     virtual bool isPresentationAttribute(const QualifiedName&) const { return false; }
    656 
    657     void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, CSSValueID identifier);
    658     void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes);
    659     void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const String& value);
    660 
    661     virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
    662 
    663     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
    664     virtual void removedFrom(ContainerNode*) OVERRIDE;
    665     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE;
    666     virtual void removeAllEventListeners() OVERRIDE FINAL;
    667 
    668     virtual void willRecalcStyle(StyleChange);
    669     virtual void didRecalcStyle(StyleChange);
    670     virtual PassRefPtr<RenderStyle> customStyleForRenderer();
    671 
    672     virtual bool shouldRegisterAsNamedItem() const { return false; }
    673     virtual bool shouldRegisterAsExtraNamedItem() const { return false; }
    674 
    675     void clearTabIndexExplicitlyIfNeeded();
    676     void setTabIndexExplicitly(short);
    677     virtual short tabIndex() const OVERRIDE;
    678     // Subclasses may override this method to affect focusability. Unlike
    679     // supportsFocus, this method must be called on an up-to-date layout, so it
    680     // may use the renderer to reason about focusability. This method cannot be
    681     // moved to RenderObject because some focusable nodes don't have renderers,
    682     // e.g., HTMLOptionElement.
    683     virtual bool rendererIsFocusable() const;
    684     PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType);
    685     HTMLCollection* cachedHTMLCollection(CollectionType);
    686 
    687     // classAttributeChanged() exists to share code between
    688     // parseAttribute (called via setAttribute()) and
    689     // svgAttributeChanged (called when element.className.baseValue is set)
    690     void classAttributeChanged(const AtomicString& newClassString);
    691 
    692 private:
    693     void styleAttributeChanged(const AtomicString& newStyleString, AttributeModificationReason);
    694 
    695     void inlineStyleChanged();
    696     PropertySetCSSStyleDeclaration* inlineStyleCSSOMWrapper();
    697     void setInlineStyleFromString(const AtomicString&);
    698     MutableStylePropertySet* ensureMutableInlineStyle();
    699 
    700     void makePresentationAttributeCacheKey(PresentationAttributeCacheKey&) const;
    701     void rebuildPresentationAttributeStyle();
    702 
    703     void updatePseudoElement(PseudoId, StyleChange);
    704     void createPseudoElementIfNeeded(PseudoId);
    705 
    706     // FIXME: Everyone should allow author shadows.
    707     virtual bool areAuthorShadowsAllowed() const { return true; }
    708     virtual void didAddUserAgentShadowRoot(ShadowRoot*) { }
    709     virtual bool alwaysCreateUserAgentShadowRoot() const { return false; }
    710 
    711     // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute.
    712     friend class Attr;
    713 
    714     enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute };
    715 
    716     void didAddAttribute(const QualifiedName&, const AtomicString&);
    717     void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
    718     void didModifyAttribute(const QualifiedName&, const AtomicString&);
    719     void didRemoveAttribute(const QualifiedName&);
    720 
    721     void synchronizeAttribute(const QualifiedName&) const;
    722     void synchronizeAttribute(const AtomicString& localName) const;
    723 
    724     void updateId(const AtomicString& oldId, const AtomicString& newId);
    725     void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
    726     void updateName(const AtomicString& oldName, const AtomicString& newName);
    727     void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
    728 
    729     void scrollByUnits(int units, ScrollGranularity);
    730 
    731     virtual void setPrefix(const AtomicString&, ExceptionState&) OVERRIDE FINAL;
    732     virtual NodeType nodeType() const OVERRIDE FINAL;
    733     virtual bool childTypeAllowed(NodeType) const OVERRIDE FINAL;
    734 
    735     void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
    736     void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute);
    737     void removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute);
    738     void attributeChangedFromParserOrByCloning(const QualifiedName&, const AtomicString&, AttributeModificationReason);
    739 
    740 #ifndef NDEBUG
    741     virtual void formatForDebugger(char* buffer, unsigned length) const;
    742 #endif
    743 
    744     bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
    745 
    746     void cancelFocusAppearanceUpdate();
    747 
    748     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
    749 
    750     // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
    751     // are used instead.
    752     virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE;
    753     virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
    754 
    755     QualifiedName m_tagName;
    756     bool rareDataStyleAffectedByEmpty() const;
    757     bool rareDataChildrenAffectedByHover() const;
    758     bool rareDataChildrenAffectedByActive() const;
    759     bool rareDataChildrenAffectedByDrag() const;
    760     bool rareDataChildrenAffectedByFirstChildRules() const;
    761     bool rareDataChildrenAffectedByLastChildRules() const;
    762     bool rareDataChildrenAffectedByDirectAdjacentRules() const;
    763     bool rareDataChildrenAffectedByForwardPositionalRules() const;
    764     bool rareDataChildrenAffectedByBackwardPositionalRules() const;
    765     unsigned rareDataChildIndex() const;
    766 
    767     SpellcheckAttributeState spellcheckAttributeState() const;
    768 
    769     void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
    770     void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
    771 
    772     void unregisterNamedFlowContentNode();
    773 
    774     void createUniqueElementData();
    775 
    776     bool shouldInvalidateDistributionWhenAttributeChanged(ElementShadow*, const QualifiedName&, const AtomicString&);
    777 
    778     ElementRareData* elementRareData() const;
    779     ElementRareData* ensureElementRareData();
    780 
    781     void detachAllAttrNodesFromElement();
    782     void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
    783     void detachAttrNodeAtIndex(Attr*, size_t index);
    784 
    785     bool isJavaScriptURLAttribute(const Attribute&) const;
    786 
    787     RefPtr<ElementData> m_elementData;
    788 };
    789 
    790 inline Element* toElement(Node* node)
    791 {
    792     ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode());
    793     return static_cast<Element*>(node);
    794 }
    795 
    796 inline const Element* toElement(const Node* node)
    797 {
    798     ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isElementNode());
    799     return static_cast<const Element*>(node);
    800 }
    801 
    802 // This will catch anyone doing an unnecessary cast.
    803 void toElement(const Element*);
    804 
    805 inline bool isDisabledFormControl(const Node* node)
    806 {
    807     return node->isElementNode() && toElement(node)->isDisabledFormControl();
    808 }
    809 
    810 inline bool Node::hasTagName(const QualifiedName& name) const
    811 {
    812     return isElementNode() && toElement(this)->hasTagName(name);
    813 }
    814 
    815 inline bool Node::hasLocalName(const AtomicString& name) const
    816 {
    817     return isElementNode() && toElement(this)->hasLocalName(name);
    818 }
    819 
    820 inline bool Node::hasAttributes() const
    821 {
    822     return isElementNode() && toElement(this)->hasAttributes();
    823 }
    824 
    825 inline NamedNodeMap* Node::attributes() const
    826 {
    827     return isElementNode() ? toElement(this)->attributes() : 0;
    828 }
    829 
    830 inline Element* Node::parentElement() const
    831 {
    832     ContainerNode* parent = parentNode();
    833     return parent && parent->isElementNode() ? toElement(parent) : 0;
    834 }
    835 
    836 inline Element* Node::previousElementSibling() const
    837 {
    838     Node* n = previousSibling();
    839     while (n && !n->isElementNode())
    840         n = n->previousSibling();
    841     return toElement(n);
    842 }
    843 
    844 inline Element* Node::nextElementSibling() const
    845 {
    846     Node* n = nextSibling();
    847     while (n && !n->isElementNode())
    848         n = n->nextSibling();
    849     return toElement(n);
    850 }
    851 
    852 inline bool Element::fastHasAttribute(const QualifiedName& name) const
    853 {
    854     ASSERT(fastAttributeLookupAllowed(name));
    855     return elementData() && getAttributeItem(name);
    856 }
    857 
    858 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
    859 {
    860     ASSERT(fastAttributeLookupAllowed(name));
    861     if (elementData()) {
    862         if (const Attribute* attribute = getAttributeItem(name))
    863             return attribute->value();
    864     }
    865     return nullAtom;
    866 }
    867 
    868 inline bool Element::hasAttributesWithoutUpdate() const
    869 {
    870     return elementData() && !elementData()->isEmpty();
    871 }
    872 
    873 inline const AtomicString& Element::idForStyleResolution() const
    874 {
    875     ASSERT(hasID());
    876     return elementData()->idForStyleResolution();
    877 }
    878 
    879 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
    880 {
    881     // FIXME: This check is probably not correct for the case where the document has an id attribute
    882     // with a non-null namespace, because it will return false, a false negative, if the prefixes
    883     // don't match but the local name and namespace both do. However, since this has been like this
    884     // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
    885     return attributeName == document()->idAttributeName();
    886 }
    887 
    888 inline const AtomicString& Element::getIdAttribute() const
    889 {
    890     return hasID() ? fastGetAttribute(document()->idAttributeName()) : nullAtom;
    891 }
    892 
    893 inline const AtomicString& Element::getNameAttribute() const
    894 {
    895     return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom;
    896 }
    897 
    898 inline const AtomicString& Element::getClassAttribute() const
    899 {
    900     if (!hasClass())
    901         return nullAtom;
    902     if (isSVGElement())
    903         return getAttribute(HTMLNames::classAttr);
    904     return fastGetAttribute(HTMLNames::classAttr);
    905 }
    906 
    907 inline void Element::setIdAttribute(const AtomicString& value)
    908 {
    909     setAttribute(document()->idAttributeName(), value);
    910 }
    911 
    912 inline const SpaceSplitString& Element::classNames() const
    913 {
    914     ASSERT(hasClass());
    915     ASSERT(elementData());
    916     return elementData()->classNames();
    917 }
    918 
    919 inline size_t Element::attributeCount() const
    920 {
    921     ASSERT(elementData());
    922     return elementData()->length();
    923 }
    924 
    925 inline const Attribute* Element::attributeItem(unsigned index) const
    926 {
    927     ASSERT(elementData());
    928     return elementData()->attributeItem(index);
    929 }
    930 
    931 inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const
    932 {
    933     ASSERT(elementData());
    934     return elementData()->getAttributeItem(name);
    935 }
    936 
    937 inline bool Element::hasID() const
    938 {
    939     return elementData() && elementData()->hasID();
    940 }
    941 
    942 inline bool Element::hasClass() const
    943 {
    944     return elementData() && elementData()->hasClass();
    945 }
    946 
    947 inline UniqueElementData* Element::ensureUniqueElementData()
    948 {
    949     if (!elementData() || !elementData()->isUnique())
    950         createUniqueElementData();
    951     return static_cast<UniqueElementData*>(m_elementData.get());
    952 }
    953 
    954 // Put here to make them inline.
    955 inline bool Node::hasID() const
    956 {
    957     return isElementNode() && toElement(this)->hasID();
    958 }
    959 
    960 inline bool Node::hasClass() const
    961 {
    962     return isElementNode() && toElement(this)->hasClass();
    963 }
    964 
    965 inline Node::InsertionNotificationRequest Node::insertedInto(ContainerNode* insertionPoint)
    966 {
    967     ASSERT(insertionPoint->inDocument() || isContainerNode());
    968     if (insertionPoint->inDocument())
    969         setFlag(InDocumentFlag);
    970     if (parentOrShadowHostNode()->isInShadowTree())
    971         setFlag(IsInShadowTreeFlag);
    972     if (childNeedsDistributionRecalc() && !insertionPoint->childNeedsDistributionRecalc())
    973         insertionPoint->markAncestorsWithChildNeedsDistributionRecalc();
    974     return InsertionDone;
    975 }
    976 
    977 inline void Node::removedFrom(ContainerNode* insertionPoint)
    978 {
    979     ASSERT(insertionPoint->inDocument() || isContainerNode());
    980     if (insertionPoint->inDocument())
    981         clearFlag(InDocumentFlag);
    982     if (isInShadowTree() && !treeScope()->rootNode()->isShadowRoot())
    983         clearFlag(IsInShadowTreeFlag);
    984 }
    985 
    986 inline void Element::invalidateStyleAttribute()
    987 {
    988     ASSERT(elementData());
    989     elementData()->m_styleAttributeIsDirty = true;
    990 }
    991 
    992 inline const StylePropertySet* Element::presentationAttributeStyle()
    993 {
    994     if (!elementData())
    995         return 0;
    996     if (elementData()->m_presentationAttributeStyleIsDirty)
    997         rebuildPresentationAttributeStyle();
    998     return elementData()->presentationAttributeStyle();
    999 }
   1000 
   1001 inline bool isShadowHost(const Node* node)
   1002 {
   1003     return node && node->isElementNode() && toElement(node)->shadow();
   1004 }
   1005 
   1006 inline bool isShadowHost(const Element* element)
   1007 {
   1008     return element && element->shadow();
   1009 }
   1010 
   1011 inline size_t ElementData::length() const
   1012 {
   1013     if (isUnique())
   1014         return static_cast<const UniqueElementData*>(this)->m_attributeVector.size();
   1015     return m_arraySize;
   1016 }
   1017 
   1018 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
   1019 {
   1020     if (!m_isUnique)
   1021         return 0;
   1022     return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
   1023 }
   1024 
   1025 inline const Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
   1026 {
   1027     size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
   1028     if (index != notFound)
   1029         return attributeItem(index);
   1030     return 0;
   1031 }
   1032 
   1033 inline const Attribute* ElementData::attributeBase() const
   1034 {
   1035     if (m_isUnique)
   1036         return static_cast<const UniqueElementData*>(this)->m_attributeVector.begin();
   1037     return static_cast<const ShareableElementData*>(this)->m_attributeArray;
   1038 }
   1039 
   1040 inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name) const
   1041 {
   1042     const Attribute* begin = attributeBase();
   1043     for (unsigned i = 0; i < length(); ++i) {
   1044         const Attribute& attribute = begin[i];
   1045         if (attribute.name().matches(name))
   1046             return i;
   1047     }
   1048     return notFound;
   1049 }
   1050 
   1051 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
   1052 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
   1053 inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const
   1054 {
   1055     unsigned len = length();
   1056     bool doSlowCheck = shouldIgnoreAttributeCase;
   1057 
   1058     // Optimize for the case where the attribute exists and its name exactly matches.
   1059     const Attribute* begin = attributeBase();
   1060     for (unsigned i = 0; i < len; ++i) {
   1061         const Attribute& attribute = begin[i];
   1062         if (!attribute.name().hasPrefix()) {
   1063             if (name == attribute.localName())
   1064                 return i;
   1065         } else
   1066             doSlowCheck = true;
   1067     }
   1068 
   1069     if (doSlowCheck)
   1070         return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
   1071     return notFound;
   1072 }
   1073 
   1074 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
   1075 {
   1076     const Attribute* begin = attributeBase();
   1077     for (unsigned i = 0; i < length(); ++i) {
   1078         const Attribute& attribute = begin[i];
   1079         if (attribute.name().matches(name))
   1080             return &attribute;
   1081     }
   1082     return 0;
   1083 }
   1084 
   1085 inline const Attribute* ElementData::attributeItem(unsigned index) const
   1086 {
   1087     RELEASE_ASSERT(index < length());
   1088     return attributeBase() + index;
   1089 }
   1090 
   1091 } // namespace
   1092 
   1093 #endif
   1094