Make elements that don't have attributes smaller.
[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 "FragmentScriptingPermission.h"
31 #include "HTMLNames.h"
32 #include "NamedNodeMap.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 WebKitAnimationList;
46
47 enum SpellcheckAttributeState {
48     SpellcheckAttributeTrue,
49     SpellcheckAttributeFalse,
50     SpellcheckAttributeDefault
51 };
52
53 class Element : public ContainerNode {
54 public:
55     static PassRefPtr<Element> create(const QualifiedName&, Document*);
56     virtual ~Element();
57
58     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
59     DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
60     DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
61     DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
62     DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
63     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
64     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
65     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
66     DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
67     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
68     DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
69     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
70     DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
71     DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
72     DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
73     DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
74     DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
75     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
76     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
77     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
78     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
79     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
80     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
81     DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
82     DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
83     DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
84
85     // These four attribute event handler attributes are overridden by HTMLBodyElement
86     // and HTMLFrameSetElement to forward to the DOMWindow.
87     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
88     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
89     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
90     DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
91
92     // WebKit extensions
93     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
94     DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
95     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
96     DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
97     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
98     DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
99     DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
100     DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
101     DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
102 #if ENABLE(TOUCH_EVENTS)
103     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
104     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
105     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
106     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
107 #endif
108 #if ENABLE(FULLSCREEN_API)
109     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
110     DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
111 #endif
112
113     bool hasAttribute(const QualifiedName&) const;
114     const AtomicString& getAttribute(const QualifiedName&) const;
115     void setAttribute(const QualifiedName&, const AtomicString& value);
116     void removeAttribute(const QualifiedName&);
117
118     // Typed getters and setters for language bindings.
119     int getIntegralAttribute(const QualifiedName& attributeName) const;
120     void setIntegralAttribute(const QualifiedName& attributeName, int value);
121     unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
122     void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
123
124     // Call this to get the value of an attribute that is known not to be the style
125     // attribute or one of the SVG animatable attributes.
126     bool fastHasAttribute(const QualifiedName&) const;
127     const AtomicString& fastGetAttribute(const QualifiedName&) const;
128 #ifndef NDEBUG
129     bool fastAttributeLookupAllowed(const QualifiedName&) const;
130 #endif
131
132     bool hasAttributes() const;
133
134     bool hasAttribute(const String& name) const;
135     bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
136
137     const AtomicString& getAttribute(const String& name) const;
138     const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
139
140     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
141     void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
142
143     bool isIdAttributeName(const QualifiedName&) const;
144     const AtomicString& getIdAttribute() const;
145     void setIdAttribute(const AtomicString&);
146
147     // Call this to get the value of the id attribute for style resolution purposes.
148     // The value will already be lowercased if the document is in compatibility mode,
149     // so this function is not suitable for non-style uses.
150     const AtomicString& idForStyleResolution() const;
151
152     void scrollIntoView(bool alignToTop = true);
153     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
154
155     void scrollByLines(int lines);
156     void scrollByPages(int pages);
157
158     int offsetLeft();
159     int offsetTop();
160     int offsetWidth();
161     int offsetHeight();
162     Element* offsetParent();
163     int clientLeft();
164     int clientTop();
165     int clientWidth();
166     int clientHeight();
167     virtual int scrollLeft();
168     virtual int scrollTop();
169     virtual void setScrollLeft(int);
170     virtual void setScrollTop(int);
171     virtual int scrollWidth();
172     virtual int scrollHeight();
173
174     LayoutRect boundsInRootViewSpace();
175
176     PassRefPtr<ClientRectList> getClientRects();
177     PassRefPtr<ClientRect> getBoundingClientRect();
178     
179     // Returns the absolute bounding box translated into screen coordinates:
180     LayoutRect screenRect() const;
181
182     void removeAttribute(const String& name);
183     void removeAttributeNS(const String& namespaceURI, const String& localName);
184
185     PassRefPtr<Attr> getAttributeNode(const String& name);
186     PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
187     PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
188     PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
189     PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
190     
191     virtual CSSStyleDeclaration* style();
192
193     const QualifiedName& tagQName() const { return m_tagName; }
194     String tagName() const { return nodeName(); }
195     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
196     
197     // A fast function for checking the local name against another atomic string.
198     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
199     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
200
201     const AtomicString& localName() const { return m_tagName.localName(); }
202     const AtomicString& prefix() const { return m_tagName.prefix(); }
203     const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
204
205     virtual KURL baseURI() const;
206
207     virtual String nodeName() const;
208
209     PassRefPtr<Element> cloneElementWithChildren();
210     PassRefPtr<Element> cloneElementWithoutChildren();
211
212     void normalizeAttributes();
213     String nodeNamePreservingCase() const;
214
215     void setBooleanAttribute(const QualifiedName& name, bool);
216
217     NamedNodeMap* attributes(bool readonly = false) const;
218
219     // This method is called whenever an attribute is added, changed or removed.
220     virtual void attributeChanged(Attribute*, bool preserveDecls = false);
221
222     // Only called by the parser immediately after element construction.
223     void parserSetAttributeMap(PassOwnPtr<NamedNodeMap>, FragmentScriptingPermission);
224
225     NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
226     NamedNodeMap* ensureAttributeMap();
227
228     ElementAttributeData* attributeData() const { return m_attributeMap ? m_attributeMap->attributeData() : 0; }
229     ElementAttributeData* ensureAttributeData() const { return attributes()->attributeData(); }
230
231     void setAttributesFromElement(const Element&);
232
233     virtual void copyNonAttributeProperties(const Element* source);
234
235     virtual void attach();
236     virtual void detach();
237     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
238     void recalcStyle(StyleChange = NoChange);
239
240     ShadowRoot* shadowRoot() const;
241     void setShadowRoot(PassRefPtr<ShadowRoot>, ExceptionCode&);
242     ShadowRoot* ensureShadowRoot();
243     void removeShadowRoot();
244
245     virtual const AtomicString& shadowPseudoId() const;
246     void setShadowPseudoId(const AtomicString&, ExceptionCode& = ASSERT_NO_EXCEPTION);
247
248     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
249
250     void setStyleAffectedByEmpty();
251     bool styleAffectedByEmpty() const;
252
253     AtomicString computeInheritedLanguage() const;
254
255     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
256
257     virtual bool isURLAttribute(Attribute*) const;
258
259     KURL getURLAttribute(const QualifiedName&) const;
260     KURL getNonEmptyURLAttribute(const QualifiedName&) const;
261
262     virtual const QualifiedName& imageSourceAttributeName() const;
263     virtual String target() const { return String(); }
264
265     virtual void focus(bool restorePreviousSelection = true);
266     virtual void updateFocusAppearance(bool restorePreviousSelection);
267     void blur();
268
269     String innerText();
270     String outerText();
271  
272     virtual String title() const;
273
274     void updateId(const AtomicString& oldId, const AtomicString& newId);
275     void updateName(const AtomicString& oldName, const AtomicString& newName);
276
277     void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
278     void willRemoveAttribute(const QualifiedName&, const AtomicString& value);
279     void didModifyAttribute(Attribute*);
280     void didRemoveAttribute(Attribute*);
281
282     LayoutSize minimumSizeForResizing() const;
283     void setMinimumSizeForResizing(const LayoutSize&);
284
285     // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
286     virtual void documentWillSuspendForPageCache() { }
287     virtual void documentDidResumeFromPageCache() { }
288
289     // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
290     virtual void mediaVolumeDidChange() { }
291
292     // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
293     virtual void privateBrowsingStateDidChange() { }
294
295     virtual void didBecomeFullscreenElement() { }
296     virtual void willStopBeingFullscreenElement() { }
297
298     bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
299     virtual void finishParsingChildren();
300     virtual void beginParsingChildren();
301
302     // ElementTraversal API
303     Element* firstElementChild() const;
304     Element* lastElementChild() const;
305     Element* previousElementSibling() const;
306     Element* nextElementSibling() const;
307     unsigned childElementCount() const;
308
309 #if ENABLE(STYLE_SCOPED)
310     void registerScopedHTMLStyleChild();
311     void unregisterScopedHTMLStyleChild();
312     bool hasScopedHTMLStyleChild() const;
313     size_t numberOfScopedHTMLStyleChildren() const;
314 #endif
315
316     bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
317
318     DOMTokenList* classList();
319     DOMTokenList* optionalClassList() const;
320
321     DOMStringMap* dataset();
322
323 #if ENABLE(MATHML)
324     virtual bool isMathMLElement() const { return false; }
325 #else
326     static bool isMathMLElement() { return false; }
327 #endif
328
329 #if ENABLE(VIDEO)
330     virtual bool isMediaElement() const { return false; }
331 #endif
332
333 #if ENABLE(INPUT_SPEECH)
334     virtual bool isInputFieldSpeechButtonElement() const { return false; }
335 #endif
336
337     virtual bool isFormControlElement() const { return false; }
338     virtual bool isEnabledFormControl() const { return true; }
339     virtual bool isReadOnlyFormControl() const { return false; }
340     virtual bool isSpinButtonElement() const { return false; }
341     virtual bool isTextFormControl() const { return false; }
342     virtual bool isOptionalFormControl() const { return false; }
343     virtual bool isRequiredFormControl() const { return false; }
344     virtual bool isDefaultButtonForForm() const { return false; }
345     virtual bool willValidate() const { return false; }
346     virtual bool isValidFormControlElement() { return false; }
347     virtual bool hasUnacceptableValue() const { return false; }
348     virtual bool isInRange() const { return false; }
349     virtual bool isOutOfRange() const { return false; }
350     virtual bool isFrameElementBase() const { return false; }
351
352     virtual bool canContainRangeEndPoint() const { return true; }
353
354     virtual const AtomicString& formControlName() const { return nullAtom; }
355     virtual const AtomicString& formControlType() const { return nullAtom; }
356
357     virtual bool wasChangedSinceLastFormControlChangeEvent() const;
358     virtual void setChangedSinceLastFormControlChangeEvent(bool);
359     virtual void dispatchFormControlChangeEvent() { }
360
361 #if ENABLE(SVG)
362     virtual bool childShouldCreateRenderer(Node*) const; 
363 #endif
364     
365 #if ENABLE(FULLSCREEN_API)
366     enum {
367         ALLOW_KEYBOARD_INPUT = 1
368     };
369     
370     void webkitRequestFullScreen(unsigned short flags);
371     virtual bool containsFullScreenElement() const;
372     virtual void setContainsFullScreenElement(bool);
373     virtual void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
374 #endif
375
376     virtual bool isSpellCheckingEnabled() const;
377
378     PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
379     
380     PassRefPtr<RenderStyle> styleForRenderer();
381
382 protected:
383     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
384         : ContainerNode(document, type)
385         , m_tagName(tagName)
386     {
387     }
388
389     virtual void willRemove();
390     virtual void insertedIntoDocument();
391     virtual void removedFromDocument();
392     virtual void insertedIntoTree(bool);
393     virtual void removedFromTree(bool);
394     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
395     virtual bool willRecalcStyle(StyleChange) { return true; }
396     virtual void didRecalcStyle(StyleChange) { }
397     virtual PassRefPtr<RenderStyle> customStyleForRenderer();
398
399     virtual bool shouldRegisterAsNamedItem() const { return false; }
400     virtual bool shouldRegisterAsExtraNamedItem() const { return false; }
401
402     // The implementation of Element::attributeChanged() calls the following two functions.
403     // They are separated to allow a different flow of control in StyledElement::attributeChanged().
404     void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
405     void updateAfterAttributeChanged(Attribute*);
406     
407     void idAttributeChanged(Attribute*);
408
409     HTMLCollection* ensureCachedHTMLCollection(CollectionType);
410
411 private:
412     void scrollByUnits(int units, ScrollGranularity);
413
414     virtual void setPrefix(const AtomicString&, ExceptionCode&);
415     virtual NodeType nodeType() const;
416     virtual bool childTypeAllowed(NodeType) const;
417
418     void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value);
419     virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
420     
421 #ifndef NDEBUG
422     virtual void formatForDebugger(char* buffer, unsigned length) const;
423 #endif
424
425     bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
426
427     void createAttributeMap() const;
428
429     virtual void updateStyleAttribute() const { }
430
431 #if ENABLE(SVG)
432     virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
433 #endif
434
435     void cancelFocusAppearanceUpdate();
436
437     virtual const AtomicString& virtualPrefix() const { return prefix(); }
438     virtual const AtomicString& virtualLocalName() const { return localName(); }
439     virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
440     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
441     
442     // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
443     // are used instead.
444     virtual PassRefPtr<Node> cloneNode(bool deep);
445     virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
446
447     QualifiedName m_tagName;
448     virtual OwnPtr<NodeRareData> createRareData();
449
450     ElementRareData* rareData() const;
451     ElementRareData* ensureRareData();
452
453     SpellcheckAttributeState spellcheckAttributeState() const;
454
455     void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
456     void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
457
458 private:
459     mutable OwnPtr<NamedNodeMap> m_attributeMap;
460 };
461     
462 inline Element* toElement(Node* node)
463 {
464     ASSERT(!node || node->isElementNode());
465     return static_cast<Element*>(node);
466 }
467
468 inline const Element* toElement(const Node* node)
469 {
470     ASSERT(!node || node->isElementNode());
471     return static_cast<const Element*>(node);
472 }
473
474 // This will catch anyone doing an unnecessary cast.
475 void toElement(const Element*);
476
477 inline bool Node::hasTagName(const QualifiedName& name) const
478 {
479     return isElementNode() && toElement(this)->hasTagName(name);
480 }
481     
482 inline bool Node::hasLocalName(const AtomicString& name) const
483 {
484     return isElementNode() && toElement(this)->hasLocalName(name);
485 }
486
487 inline bool Node::hasAttributes() const
488 {
489     return isElementNode() && toElement(this)->hasAttributes();
490 }
491
492 inline NamedNodeMap* Node::attributes() const
493 {
494     return isElementNode() ? toElement(this)->attributes() : 0;
495 }
496
497 inline Element* Node::parentElement() const
498 {
499     ContainerNode* parent = parentNode();
500     return parent && parent->isElementNode() ? toElement(parent) : 0;
501 }
502
503 inline NamedNodeMap* Element::attributes(bool readonly) const
504 {
505     if (!isStyleAttributeValid())
506         updateStyleAttribute();
507
508 #if ENABLE(SVG)
509     if (!areSVGAttributesValid())
510         updateAnimatedSVGAttribute(anyQName());
511 #endif
512
513     if (!readonly && !m_attributeMap)
514         createAttributeMap();
515     return m_attributeMap.get();
516 }
517
518 inline void Element::setAttributesFromElement(const Element& other)
519 {
520     if (NamedNodeMap* attributeMap = other.attributes(true))
521         attributes(false)->setAttributes(*attributeMap);
522 }
523
524 inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
525 {
526     if (!inDocument())
527         return;
528
529     if (oldName == newName)
530         return;
531
532     if (shouldRegisterAsNamedItem())
533         updateNamedItemRegistration(oldName, newName);
534 }
535
536 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
537 {
538     if (!inDocument())
539         return;
540
541     if (oldId == newId)
542         return;
543
544     TreeScope* scope = treeScope();
545     if (!oldId.isEmpty())
546         scope->removeElementById(oldId, this);
547     if (!newId.isEmpty())
548         scope->addElementById(newId, this);
549
550     if (shouldRegisterAsExtraNamedItem())
551         updateExtraNamedItemRegistration(oldId, newId);
552 }
553
554 inline void Element::willRemoveAttribute(const QualifiedName& name, const AtomicString& value)
555 {
556     if (!value.isNull())
557         willModifyAttribute(name, value, nullAtom);
558 }
559
560 inline bool Element::fastHasAttribute(const QualifiedName& name) const
561 {
562     ASSERT(fastAttributeLookupAllowed(name));
563     return m_attributeMap && m_attributeMap->getAttributeItem(name);
564 }
565
566 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
567 {
568     ASSERT(fastAttributeLookupAllowed(name));
569     if (m_attributeMap) {
570         if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
571             return attribute->value();
572     }
573     return nullAtom;
574 }
575
576 inline const AtomicString& Element::idForStyleResolution() const
577 {
578     ASSERT(hasID());
579     return attributeData()->idForStyleResolution();
580 }
581
582 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
583 {
584     // FIXME: This check is probably not correct for the case where the document has an id attribute
585     // with a non-null namespace, because it will return false, a false negative, if the prefixes
586     // don't match but the local name and namespace both do. However, since this has been like this
587     // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
588     return attributeName == document()->idAttributeName();
589 }
590
591 inline const AtomicString& Element::getIdAttribute() const
592 {
593     return fastGetAttribute(document()->idAttributeName());
594 }
595
596 inline void Element::setIdAttribute(const AtomicString& value)
597 {
598     setAttribute(document()->idAttributeName(), value);
599 }
600
601 inline NamedNodeMap* Element::ensureAttributeMap()
602 {
603     if (!m_attributeMap)
604         createAttributeMap();
605     return m_attributeMap.get();
606 }
607
608 inline Element* firstElementChild(const ContainerNode* container)
609 {
610     ASSERT_ARG(container, container);
611     Node* child = container->firstChild();
612     while (child && !child->isElementNode())
613         child = child->nextSibling();
614     return static_cast<Element*>(child);
615 }
616
617 } // namespace
618
619 #endif