e4f70cfab8bafd8b538b5cefe22f989bb23e59a3
[WebKit-https.git] / Source / WebCore / dom / Element.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Peter Kelly (pmk@post.com)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 "CollectionType.h"
29 #include "Document.h"
30 #include "ElementAttributeData.h"
31 #include "FragmentScriptingPermission.h"
32 #include "HTMLNames.h"
33 #include "ScrollTypes.h"
34
35 namespace WebCore {
36
37 class Attribute;
38 class ClientRect;
39 class ClientRectList;
40 class DOMStringMap;
41 class DOMTokenList;
42 class ElementRareData;
43 class IntSize;
44 class ShadowRoot;
45 class ElementShadow;
46 class WebKitAnimationList;
47
48 enum SpellcheckAttributeState {
49     SpellcheckAttributeTrue,
50     SpellcheckAttributeFalse,
51     SpellcheckAttributeDefault
52 };
53
54 class Element : public ContainerNode {
55 public:
56     static PassRefPtr<Element> create(const QualifiedName&, Document*);
57     virtual ~Element();
58
59     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
60     DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
61     DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
62     DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
63     DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
64     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
65     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
66     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
67     DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
68     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
69     DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
70     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
71     DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
72     DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
73     DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
74     DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
75     DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
76     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
77     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
78     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
79     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
80     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
81     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
82     DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
83     DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
84     DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
85
86     // These four attribute event handler attributes are overridden by HTMLBodyElement
87     // and HTMLFrameSetElement to forward to the DOMWindow.
88     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
89     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
90     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
91     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
92
93     // WebKit extensions
94     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
95     DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
96     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
97     DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
98     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
99     DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
100     DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
101     DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
102     DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
103 #if ENABLE(TOUCH_EVENTS)
104     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
105     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
106     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
107     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
108 #endif
109 #if ENABLE(FULLSCREEN_API)
110     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
111     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
112 #endif
113
114     bool hasAttribute(const QualifiedName&) const;
115     const AtomicString& getAttribute(const QualifiedName&) const;
116     void setAttribute(const QualifiedName&, const AtomicString& value, EInUpdateStyleAttribute = NotInUpdateStyleAttribute);
117     void removeAttribute(const QualifiedName&);
118     void removeAttribute(size_t index);
119
120     // Typed getters and setters for language bindings.
121     int getIntegralAttribute(const QualifiedName& attributeName) const;
122     void setIntegralAttribute(const QualifiedName& attributeName, int value);
123     unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
124     void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
125
126     // Call this to get the value of an attribute that is known not to be the style
127     // attribute or one of the SVG animatable attributes.
128     bool fastHasAttribute(const QualifiedName&) const;
129     const AtomicString& fastGetAttribute(const QualifiedName&) const;
130 #ifndef NDEBUG
131     bool fastAttributeLookupAllowed(const QualifiedName&) const;
132 #endif
133
134 #ifdef DUMP_NODE_STATISTICS
135     bool hasNamedNodeMap() const;
136 #endif
137     bool hasAttributes() const;
138     // This variant will not update the potentially invalid attributes. To be used when not interested
139     // in style attribute or one of the SVG animation attributes.
140     bool hasAttributesWithoutUpdate() const;
141
142     bool hasAttribute(const String& name) const;
143     bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
144
145     const AtomicString& getAttribute(const AtomicString& name) const;
146     const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
147
148     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
149     void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = AllowScriptingContent);
150
151     bool isIdAttributeName(const QualifiedName&) const;
152     const AtomicString& getIdAttribute() const;
153     void setIdAttribute(const AtomicString&);
154
155     const AtomicString& getNameAttribute() const;
156
157     // Call this to get the value of the id attribute for style resolution purposes.
158     // The value will already be lowercased if the document is in compatibility mode,
159     // so this function is not suitable for non-style uses.
160     const AtomicString& idForStyleResolution() const;
161
162     // Internal methods that assume the existence of attribute storage, one should use hasAttributes()
163     // before calling them.
164     size_t attributeCount() const;
165     Attribute* attributeItem(unsigned index) const;
166     Attribute* getAttributeItem(const QualifiedName&) const;
167     size_t getAttributeItemIndex(const QualifiedName& name) const { return attributeData()->getAttributeItemIndex(name); }
168     size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return attributeData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); }
169
170     void scrollIntoView(bool alignToTop = true);
171     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
172
173     void scrollByLines(int lines);
174     void scrollByPages(int pages);
175
176     int offsetLeft();
177     int offsetTop();
178     int offsetWidth();
179     int offsetHeight();
180     Element* offsetParent();
181     int clientLeft();
182     int clientTop();
183     int clientWidth();
184     int clientHeight();
185     virtual int scrollLeft();
186     virtual int scrollTop();
187     virtual void setScrollLeft(int);
188     virtual void setScrollTop(int);
189     virtual int scrollWidth();
190     virtual int scrollHeight();
191
192     IntRect boundsInRootViewSpace();
193
194     PassRefPtr<ClientRectList> getClientRects();
195     PassRefPtr<ClientRect> getBoundingClientRect();
196     
197     // Returns the absolute bounding box translated into screen coordinates:
198     IntRect screenRect() const;
199
200     void removeAttribute(const String& name);
201     void removeAttributeNS(const String& namespaceURI, const String& localName);
202
203     PassRefPtr<Attr> detachAttribute(size_t index);
204
205     PassRefPtr<Attr> getAttributeNode(const String& name);
206     PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
207     PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
208     PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
209     PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
210
211     PassRefPtr<Attr> attrIfExists(const QualifiedName&);
212     PassRefPtr<Attr> ensureAttr(const QualifiedName&);
213     
214     virtual CSSStyleDeclaration* style();
215
216     const QualifiedName& tagQName() const { return m_tagName; }
217     String tagName() const { return nodeName(); }
218     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
219     
220     // A fast function for checking the local name against another atomic string.
221     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
222     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
223
224     const AtomicString& localName() const { return m_tagName.localName(); }
225     const AtomicString& prefix() const { return m_tagName.prefix(); }
226     const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
227
228     virtual KURL baseURI() const;
229
230     virtual String nodeName() const;
231
232     PassRefPtr<Element> cloneElementWithChildren();
233     PassRefPtr<Element> cloneElementWithoutChildren();
234
235     void normalizeAttributes();
236     String nodeNamePreservingCase() const;
237
238     void setBooleanAttribute(const QualifiedName& name, bool);
239
240     // For exposing to DOM only.
241     NamedNodeMap* attributes() const;
242
243     // This method is called whenever an attribute is added, changed or removed.
244     virtual void attributeChanged(const Attribute&);
245
246     // Only called by the parser immediately after element construction.
247     void parserSetAttributes(const Vector<Attribute>&, FragmentScriptingPermission);
248
249     ElementAttributeData* attributeData() const { return m_attributeData.get(); }
250     ElementAttributeData* ensureAttributeData() const;
251     ElementAttributeData* updatedAttributeData() const;
252     ElementAttributeData* ensureUpdatedAttributeData() const;
253
254     // Clones attributes only.
255     void cloneAttributesFromElement(const Element&);
256
257     // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.)
258     void cloneDataFromElement(const Element&);
259
260     bool hasEquivalentAttributes(const Element* other) const;
261
262     virtual void copyNonAttributePropertiesFromElement(const Element&) { }
263
264     virtual void attach();
265     virtual void detach();
266     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
267     void recalcStyle(StyleChange = NoChange);
268
269     ElementShadow* shadow() const;
270     ElementShadow* ensureShadow();
271
272     // FIXME: Remove Element::ensureShadowRoot
273     // https://bugs.webkit.org/show_bug.cgi?id=77608
274     ShadowRoot* ensureShadowRoot();
275
276     virtual const AtomicString& shadowPseudoId() const;
277     void setShadowPseudoId(const AtomicString&, ExceptionCode& = ASSERT_NO_EXCEPTION);
278
279     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
280
281     void setStyleAffectedByEmpty();
282     bool styleAffectedByEmpty() const;
283
284     AtomicString computeInheritedLanguage() const;
285
286     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
287
288     virtual bool isURLAttribute(const Attribute&) const { return false; }
289
290     KURL getURLAttribute(const QualifiedName&) const;
291     KURL getNonEmptyURLAttribute(const QualifiedName&) const;
292
293     virtual const QualifiedName& imageSourceAttributeName() const;
294     virtual String target() const { return String(); }
295
296     virtual void focus(bool restorePreviousSelection = true);
297     virtual void updateFocusAppearance(bool restorePreviousSelection);
298     void blur();
299
300     String innerText();
301     String outerText();
302  
303     virtual String title() const;
304
305     void updateId(const AtomicString& oldId, const AtomicString& newId);
306     void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
307     void updateName(const AtomicString& oldName, const AtomicString& newName);
308
309     void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
310     void willRemoveAttribute(const QualifiedName&, const AtomicString& value);
311     void didAddAttribute(const Attribute&);
312     void didModifyAttribute(const Attribute&);
313     void didRemoveAttribute(const QualifiedName&);
314
315     LayoutSize minimumSizeForResizing() const;
316     void setMinimumSizeForResizing(const LayoutSize&);
317
318     // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
319     virtual void documentWillSuspendForPageCache() { }
320     virtual void documentDidResumeFromPageCache() { }
321
322     // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
323     virtual void mediaVolumeDidChange() { }
324
325     // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
326     virtual void privateBrowsingStateDidChange() { }
327
328     virtual void didBecomeFullscreenElement() { }
329     virtual void willStopBeingFullscreenElement() { }
330
331     bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
332     virtual void finishParsingChildren();
333     virtual void beginParsingChildren();
334
335     // ElementTraversal API
336     Element* firstElementChild() const;
337     Element* lastElementChild() const;
338     Element* previousElementSibling() const;
339     Element* nextElementSibling() const;
340     unsigned childElementCount() const;
341
342     bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
343
344     DOMTokenList* classList();
345     DOMTokenList* optionalClassList() const;
346
347     DOMStringMap* dataset();
348
349 #if ENABLE(MATHML)
350     virtual bool isMathMLElement() const { return false; }
351 #else
352     static bool isMathMLElement() { return false; }
353 #endif
354
355 #if ENABLE(VIDEO)
356     virtual bool isMediaElement() const { return false; }
357 #endif
358
359 #if ENABLE(INPUT_SPEECH)
360     virtual bool isInputFieldSpeechButtonElement() const { return false; }
361 #endif
362
363     virtual bool isFormControlElement() const { return false; }
364     virtual bool isEnabledFormControl() const { return true; }
365     virtual bool isReadOnlyFormControl() const { return false; }
366     virtual bool isSpinButtonElement() const { return false; }
367     virtual bool isTextFormControl() const { return false; }
368     virtual bool isOptionalFormControl() const { return false; }
369     virtual bool isRequiredFormControl() const { return false; }
370     virtual bool isDefaultButtonForForm() const { return false; }
371     virtual bool willValidate() const { return false; }
372     virtual bool isValidFormControlElement() { return false; }
373     virtual bool hasUnacceptableValue() const { return false; }
374     virtual bool isInRange() const { return false; }
375     virtual bool isOutOfRange() const { return false; }
376     virtual bool isFrameElementBase() const { return false; }
377     virtual bool isTextFieldDecoration() const { return false; }
378
379     virtual bool canContainRangeEndPoint() const { return true; }
380
381     virtual const AtomicString& formControlType() const { return nullAtom; }
382
383     virtual bool wasChangedSinceLastFormControlChangeEvent() const;
384     virtual void setChangedSinceLastFormControlChangeEvent(bool);
385     virtual void dispatchFormControlChangeEvent() { }
386
387 #if ENABLE(SVG)
388     virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const;
389 #endif
390     
391 #if ENABLE(FULLSCREEN_API)
392     enum {
393         ALLOW_KEYBOARD_INPUT = 1 << 0,
394         LEGACY_MOZILLA_REQUEST = 1 << 1,
395     };
396     
397     void webkitRequestFullScreen(unsigned short flags);
398     virtual bool containsFullScreenElement() const;
399     virtual void setContainsFullScreenElement(bool);
400     virtual void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
401
402     // W3C API
403     void webkitRequestFullscreen();
404 #endif
405
406 #if ENABLE(POINTER_LOCK)
407     void webkitRequestPointerLock();
408 #endif
409
410     virtual bool isSpellCheckingEnabled() const;
411
412     PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
413     
414     PassRefPtr<RenderStyle> styleForRenderer();
415
416     const AtomicString& webkitRegionOverflow() const;
417
418     bool hasID() const;
419     bool hasClass() const;
420
421     IntSize savedLayerScrollOffset() const;
422     void setSavedLayerScrollOffset(const IntSize&);
423
424     virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
425     {
426         memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
427         ContainerNode::reportMemoryUsage(memoryObjectInfo);
428         memoryObjectInfo->reportInstrumentedObject(m_tagName);
429         memoryObjectInfo->reportInstrumentedPointer(m_attributeData.get());
430     }
431
432 protected:
433     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
434         : ContainerNode(document, type)
435         , m_tagName(tagName)
436     {
437     }
438
439     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
440     virtual void removedFrom(ContainerNode*) OVERRIDE;
441     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
442
443     virtual bool willRecalcStyle(StyleChange);
444     virtual void didRecalcStyle(StyleChange);
445     virtual PassRefPtr<RenderStyle> customStyleForRenderer();
446
447     virtual bool shouldRegisterAsNamedItem() const { return false; }
448     virtual bool shouldRegisterAsExtraNamedItem() const { return false; }
449
450     HTMLCollection* ensureCachedHTMLCollection(CollectionType);
451
452 private:
453     void updateInvalidAttributes() const;
454
455     void scrollByUnits(int units, ScrollGranularity);
456
457     virtual void setPrefix(const AtomicString&, ExceptionCode&);
458     virtual NodeType nodeType() const;
459     virtual bool childTypeAllowed(NodeType) const;
460
461     void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value, EInUpdateStyleAttribute);
462
463 #ifndef NDEBUG
464     virtual void formatForDebugger(char* buffer, unsigned length) const;
465 #endif
466
467     bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
468
469     void createAttributeData() const;
470
471     virtual void updateStyleAttribute() const { }
472
473 #if ENABLE(SVG)
474     virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
475 #endif
476
477     void cancelFocusAppearanceUpdate();
478
479     virtual const AtomicString& virtualPrefix() const { return prefix(); }
480     virtual const AtomicString& virtualLocalName() const { return localName(); }
481     virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
482     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
483     
484     // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
485     // are used instead.
486     virtual PassRefPtr<Node> cloneNode(bool deep);
487     virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
488
489     QualifiedName m_tagName;
490     virtual OwnPtr<NodeRareData> createRareData();
491
492     SpellcheckAttributeState spellcheckAttributeState() const;
493
494     void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
495     void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
496
497     void unregisterNamedFlowContentNode();
498
499 private:
500     ElementRareData* elementRareData() const;
501     ElementRareData* ensureElementRareData();
502
503     mutable OwnPtr<ElementAttributeData> m_attributeData;
504 };
505     
506 inline Element* toElement(Node* node)
507 {
508     ASSERT(!node || node->isElementNode());
509     return static_cast<Element*>(node);
510 }
511
512 inline const Element* toElement(const Node* node)
513 {
514     ASSERT(!node || node->isElementNode());
515     return static_cast<const Element*>(node);
516 }
517
518 // This will catch anyone doing an unnecessary cast.
519 void toElement(const Element*);
520
521 inline bool Node::hasTagName(const QualifiedName& name) const
522 {
523     return isElementNode() && toElement(this)->hasTagName(name);
524 }
525     
526 inline bool Node::hasLocalName(const AtomicString& name) const
527 {
528     return isElementNode() && toElement(this)->hasLocalName(name);
529 }
530
531 inline bool Node::hasAttributes() const
532 {
533     return isElementNode() && toElement(this)->hasAttributes();
534 }
535
536 inline NamedNodeMap* Node::attributes() const
537 {
538     return isElementNode() ? toElement(this)->attributes() : 0;
539 }
540
541 inline Element* Node::parentElement() const
542 {
543     ContainerNode* parent = parentNode();
544     return parent && parent->isElementNode() ? toElement(parent) : 0;
545 }
546
547 inline Element* Element::previousElementSibling() const
548 {
549     Node* n = previousSibling();
550     while (n && !n->isElementNode())
551         n = n->previousSibling();
552     return static_cast<Element*>(n);
553 }
554
555 inline Element* Element::nextElementSibling() const
556 {
557     Node* n = nextSibling();
558     while (n && !n->isElementNode())
559         n = n->nextSibling();
560     return static_cast<Element*>(n);
561 }
562
563 inline ElementAttributeData* Element::ensureAttributeData() const
564 {
565     if (!m_attributeData)
566         createAttributeData();
567     return m_attributeData.get();
568 }
569
570 inline ElementAttributeData* Element::updatedAttributeData() const
571 {
572     updateInvalidAttributes();
573     return attributeData();
574 }
575
576 inline ElementAttributeData* Element::ensureUpdatedAttributeData() const
577 {
578     updateInvalidAttributes();
579     return ensureAttributeData();
580 }
581
582 inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
583 {
584     if (!inDocument())
585         return;
586
587     if (oldName == newName)
588         return;
589
590     if (shouldRegisterAsNamedItem())
591         updateNamedItemRegistration(oldName, newName);
592 }
593
594 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
595 {
596     if (!inDocument())
597         return;
598
599     if (oldId == newId)
600         return;
601
602     updateId(treeScope(), oldId, newId);
603 }
604
605 inline void Element::updateId(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId)
606 {
607     ASSERT(inDocument());
608     ASSERT(oldId != newId);
609
610     if (!oldId.isEmpty())
611         scope->removeElementById(oldId, this);
612     if (!newId.isEmpty())
613         scope->addElementById(newId, this);
614
615     if (shouldRegisterAsExtraNamedItem())
616         updateExtraNamedItemRegistration(oldId, newId);
617 }
618
619 inline void Element::willRemoveAttribute(const QualifiedName& name, const AtomicString& value)
620 {
621     if (!value.isNull())
622         willModifyAttribute(name, value, nullAtom);
623 }
624
625 inline bool Element::fastHasAttribute(const QualifiedName& name) const
626 {
627     ASSERT(fastAttributeLookupAllowed(name));
628     return m_attributeData && getAttributeItem(name);
629 }
630
631 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
632 {
633     ASSERT(fastAttributeLookupAllowed(name));
634     if (m_attributeData) {
635         if (Attribute* attribute = getAttributeItem(name))
636             return attribute->value();
637     }
638     return nullAtom;
639 }
640
641 inline bool Element::hasAttributesWithoutUpdate() const
642 {
643     return m_attributeData && !m_attributeData->isEmpty();
644 }
645
646 inline const AtomicString& Element::idForStyleResolution() const
647 {
648     ASSERT(hasID());
649     return m_attributeData->idForStyleResolution();
650 }
651
652 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
653 {
654     // FIXME: This check is probably not correct for the case where the document has an id attribute
655     // with a non-null namespace, because it will return false, a false negative, if the prefixes
656     // don't match but the local name and namespace both do. However, since this has been like this
657     // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
658     return attributeName == document()->idAttributeName();
659 }
660
661 inline const AtomicString& Element::getIdAttribute() const
662 {
663     return hasID() ? fastGetAttribute(document()->idAttributeName()) : nullAtom;
664 }
665
666 inline const AtomicString& Element::getNameAttribute() const
667 {
668     return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom;
669 }
670
671 inline void Element::setIdAttribute(const AtomicString& value)
672 {
673     setAttribute(document()->idAttributeName(), value);
674 }
675
676 inline size_t Element::attributeCount() const
677 {
678     ASSERT(m_attributeData);
679     return m_attributeData->length();
680 }
681
682 inline Attribute* Element::attributeItem(unsigned index) const
683 {
684     ASSERT(m_attributeData);
685     return m_attributeData->attributeItem(index);
686 }
687
688 inline Attribute* Element::getAttributeItem(const QualifiedName& name) const
689 {
690     ASSERT(m_attributeData);
691     return m_attributeData->getAttributeItem(name);
692 }
693
694 inline void Element::updateInvalidAttributes() const
695 {
696     if (!isStyleAttributeValid())
697         updateStyleAttribute();
698
699 #if ENABLE(SVG)
700     if (!areSVGAttributesValid())
701         updateAnimatedSVGAttribute(anyQName());
702 #endif
703 }
704
705 inline Element* firstElementChild(const ContainerNode* container)
706 {
707     ASSERT_ARG(container, container);
708     Node* child = container->firstChild();
709     while (child && !child->isElementNode())
710         child = child->nextSibling();
711     return static_cast<Element*>(child);
712 }
713
714 inline bool Element::hasID() const
715 {
716     return attributeData() && attributeData()->hasID();
717 }
718
719 inline bool Element::hasClass() const
720 {
721     return attributeData() && attributeData()->hasClass();
722 }
723
724 // Put here to make them inline.
725 inline bool Node::hasID() const
726 {
727     return isElementNode() && toElement(this)->hasID();
728 }
729
730 inline bool Node::hasClass() const
731 {
732     return isElementNode() && toElement(this)->hasClass();
733 }
734
735 inline bool isShadowHost(const Node* node)
736 {
737     return node && node->isElementNode() && toElement(node)->shadow();
738 }
739
740 } // namespace
741
742 #endif