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