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 *           (C) 2007 David Smith (catfish.man@gmail.com)
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
8 *           (C) 2007 Eric Seidel (eric@webkit.org)
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB.  If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#include "config.h"
27#include "Element.h"
28
29#include "AXObjectCache.h"
30#include "Attr.h"
31#include "CSSParser.h"
32#include "CSSSelectorList.h"
33#include "Chrome.h"
34#include "ChromeClient.h"
35#include "ClassList.h"
36#include "ClientRect.h"
37#include "ClientRectList.h"
38#include "CustomElementRegistry.h"
39#include "DOMTokenList.h"
40#include "DatasetDOMStringMap.h"
41#include "Document.h"
42#include "DocumentFragment.h"
43#include "DocumentSharedObjectPool.h"
44#include "ElementRareData.h"
45#include "EventDispatcher.h"
46#include "ExceptionCode.h"
47#include "FlowThreadController.h"
48#include "FocusController.h"
49#include "FocusEvent.h"
50#include "Frame.h"
51#include "FrameSelection.h"
52#include "FrameView.h"
53#include "HTMLCollection.h"
54#include "HTMLDocument.h"
55#include "HTMLElement.h"
56#include "HTMLFormControlsCollection.h"
57#include "HTMLFrameOwnerElement.h"
58#include "HTMLLabelElement.h"
59#include "HTMLNameCollection.h"
60#include "HTMLNames.h"
61#include "HTMLOptionsCollection.h"
62#include "HTMLParserIdioms.h"
63#include "HTMLTableRowsCollection.h"
64#include "InsertionPoint.h"
65#include "InspectorInstrumentation.h"
66#include "MutationObserverInterestGroup.h"
67#include "MutationRecord.h"
68#include "NamedNodeMap.h"
69#include "NodeList.h"
70#include "NodeRenderStyle.h"
71#include "NodeRenderingContext.h"
72#include "NodeTraversal.h"
73#include "Page.h"
74#include "PointerLockController.h"
75#include "PseudoElement.h"
76#include "RenderRegion.h"
77#include "RenderTheme.h"
78#include "RenderView.h"
79#include "RenderWidget.h"
80#include "SelectorQuery.h"
81#include "Settings.h"
82#include "ShadowRoot.h"
83#include "StylePropertySet.h"
84#include "StyleResolver.h"
85#include "Text.h"
86#include "TextIterator.h"
87#include "VoidCallback.h"
88#include "XMLNSNames.h"
89#include "XMLNames.h"
90#include "htmlediting.h"
91#include <wtf/BitVector.h>
92#include <wtf/CurrentTime.h>
93#include <wtf/text/CString.h>
94
95#if ENABLE(SVG)
96#include "SVGDocumentExtensions.h"
97#include "SVGElement.h"
98#include "SVGNames.h"
99#endif
100
101namespace WebCore {
102
103using namespace HTMLNames;
104using namespace XMLNames;
105
106static inline bool shouldIgnoreAttributeCase(const Element* e)
107{
108    return e && e->document()->isHTMLDocument() && e->isHTMLElement();
109}
110
111class StyleResolverParentPusher {
112public:
113    StyleResolverParentPusher(Element* parent)
114        : m_parent(parent)
115        , m_pushedStyleResolver(0)
116    {
117    }
118    void push()
119    {
120        if (m_pushedStyleResolver)
121            return;
122        m_pushedStyleResolver = m_parent->document()->ensureStyleResolver();
123        m_pushedStyleResolver->pushParentElement(m_parent);
124    }
125    ~StyleResolverParentPusher()
126    {
127
128        if (!m_pushedStyleResolver)
129            return;
130
131        // This tells us that our pushed style selector is in a bad state,
132        // so we should just bail out in that scenario.
133        ASSERT(m_pushedStyleResolver == m_parent->document()->ensureStyleResolver());
134        if (m_pushedStyleResolver != m_parent->document()->ensureStyleResolver())
135            return;
136
137        m_pushedStyleResolver->popParentElement(m_parent);
138    }
139
140private:
141    Element* m_parent;
142    StyleResolver* m_pushedStyleResolver;
143};
144
145typedef Vector<RefPtr<Attr> > AttrNodeList;
146typedef HashMap<Element*, OwnPtr<AttrNodeList> > AttrNodeListMap;
147
148static AttrNodeListMap& attrNodeListMap()
149{
150    DEFINE_STATIC_LOCAL(AttrNodeListMap, map, ());
151    return map;
152}
153
154static AttrNodeList* attrNodeListForElement(Element* element)
155{
156    if (!element->hasSyntheticAttrChildNodes())
157        return 0;
158    ASSERT(attrNodeListMap().contains(element));
159    return attrNodeListMap().get(element);
160}
161
162static AttrNodeList* ensureAttrNodeListForElement(Element* element)
163{
164    if (element->hasSyntheticAttrChildNodes()) {
165        ASSERT(attrNodeListMap().contains(element));
166        return attrNodeListMap().get(element);
167    }
168    ASSERT(!attrNodeListMap().contains(element));
169    element->setHasSyntheticAttrChildNodes(true);
170    AttrNodeListMap::AddResult result = attrNodeListMap().add(element, adoptPtr(new AttrNodeList));
171    return result.iterator->value.get();
172}
173
174static void removeAttrNodeListForElement(Element* element)
175{
176    ASSERT(element->hasSyntheticAttrChildNodes());
177    ASSERT(attrNodeListMap().contains(element));
178    attrNodeListMap().remove(element);
179    element->setHasSyntheticAttrChildNodes(false);
180}
181
182static Attr* findAttrNodeInList(AttrNodeList* attrNodeList, const QualifiedName& name)
183{
184    for (unsigned i = 0; i < attrNodeList->size(); ++i) {
185        if (attrNodeList->at(i)->qualifiedName() == name)
186            return attrNodeList->at(i).get();
187    }
188    return 0;
189}
190
191PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
192{
193    return adoptRef(new Element(tagName, document, CreateElement));
194}
195
196Element::~Element()
197{
198#ifndef NDEBUG
199    if (document() && document()->renderer()) {
200        // When the document is not destroyed, an element that was part of a named flow
201        // content nodes should have been removed from the content nodes collection
202        // and the inNamedFlow flag reset.
203        ASSERT(!inNamedFlow());
204    }
205#endif
206
207    if (hasRareData()) {
208        ElementRareData* data = elementRareData();
209        data->setPseudoElement(BEFORE, 0);
210        data->setPseudoElement(AFTER, 0);
211        data->clearShadow();
212    }
213
214    if (hasSyntheticAttrChildNodes())
215        detachAllAttrNodesFromElement();
216
217#if ENABLE(SVG)
218    if (hasPendingResources()) {
219        document()->accessSVGExtensions()->removeElementFromPendingResources(this);
220        ASSERT(!hasPendingResources());
221    }
222#endif
223}
224
225inline ElementRareData* Element::elementRareData() const
226{
227    ASSERT(hasRareData());
228    return static_cast<ElementRareData*>(rareData());
229}
230
231inline ElementRareData* Element::ensureElementRareData()
232{
233    return static_cast<ElementRareData*>(ensureRareData());
234}
235
236void Element::clearTabIndexExplicitlyIfNeeded()
237{
238    if (hasRareData())
239        elementRareData()->clearTabIndexExplicitly();
240}
241
242void Element::setTabIndexExplicitly(short tabIndex)
243{
244    ensureElementRareData()->setTabIndexExplicitly(tabIndex);
245}
246
247bool Element::supportsFocus() const
248{
249    return hasRareData() && elementRareData()->tabIndexSetExplicitly();
250}
251
252Element* Element::focusDelegate()
253{
254    return this;
255}
256
257short Element::tabIndex() const
258{
259    return hasRareData() ? elementRareData()->tabIndex() : 0;
260}
261
262bool Element::isKeyboardFocusable(KeyboardEvent*) const
263{
264    return isFocusable() && tabIndex() >= 0;
265}
266
267bool Element::isMouseFocusable() const
268{
269    return isFocusable();
270}
271
272bool Element::shouldUseInputMethod()
273{
274    return isContentEditable(UserSelectAllIsAlwaysNonEditable);
275}
276
277void Element::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickVisualOptions visualOptions)
278{
279    EventDispatcher::dispatchSimulatedClick(this, underlyingEvent, eventOptions, visualOptions);
280}
281
282DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
283DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, error);
284DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, focus);
285DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, load);
286
287PassRefPtr<Node> Element::cloneNode(bool deep)
288{
289    return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
290}
291
292PassRefPtr<Element> Element::cloneElementWithChildren()
293{
294    RefPtr<Element> clone = cloneElementWithoutChildren();
295    cloneChildNodes(clone.get());
296    return clone.release();
297}
298
299PassRefPtr<Element> Element::cloneElementWithoutChildren()
300{
301    RefPtr<Element> clone = cloneElementWithoutAttributesAndChildren();
302    // This will catch HTML elements in the wrong namespace that are not correctly copied.
303    // This is a sanity check as HTML overloads some of the DOM methods.
304    ASSERT(isHTMLElement() == clone->isHTMLElement());
305
306    clone->cloneDataFromElement(*this);
307    return clone.release();
308}
309
310PassRefPtr<Element> Element::cloneElementWithoutAttributesAndChildren()
311{
312    return document()->createElement(tagQName(), false);
313}
314
315PassRefPtr<Attr> Element::detachAttribute(unsigned index)
316{
317    ASSERT(elementData());
318
319    const Attribute* attribute = elementData()->attributeItem(index);
320    ASSERT(attribute);
321
322    RefPtr<Attr> attrNode = attrIfExists(attribute->name());
323    if (attrNode)
324        detachAttrNodeFromElementWithValue(attrNode.get(), attribute->value());
325    else
326        attrNode = Attr::create(document(), attribute->name(), attribute->value());
327
328    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
329    return attrNode.release();
330}
331
332void Element::removeAttribute(const QualifiedName& name)
333{
334    if (!elementData())
335        return;
336
337    unsigned index = elementData()->getAttributeItemIndex(name);
338    if (index == ElementData::attributeNotFound)
339        return;
340
341    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
342}
343
344void Element::setBooleanAttribute(const QualifiedName& name, bool value)
345{
346    if (value)
347        setAttribute(name, emptyAtom);
348    else
349        removeAttribute(name);
350}
351
352NamedNodeMap* Element::attributes() const
353{
354    ElementRareData* rareData = const_cast<Element*>(this)->ensureElementRareData();
355    if (NamedNodeMap* attributeMap = rareData->attributeMap())
356        return attributeMap;
357
358    rareData->setAttributeMap(NamedNodeMap::create(const_cast<Element*>(this)));
359    return rareData->attributeMap();
360}
361
362Node::NodeType Element::nodeType() const
363{
364    return ELEMENT_NODE;
365}
366
367bool Element::hasAttribute(const QualifiedName& name) const
368{
369    return hasAttributeNS(name.namespaceURI(), name.localName());
370}
371
372void Element::synchronizeAllAttributes() const
373{
374    if (!elementData())
375        return;
376    if (elementData()->m_styleAttributeIsDirty) {
377        ASSERT(isStyledElement());
378        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
379    }
380#if ENABLE(SVG)
381    if (elementData()->m_animatedSVGAttributesAreDirty) {
382        ASSERT(isSVGElement());
383        toSVGElement(this)->synchronizeAnimatedSVGAttribute(anyQName());
384    }
385#endif
386}
387
388inline void Element::synchronizeAttribute(const QualifiedName& name) const
389{
390    if (!elementData())
391        return;
392    if (UNLIKELY(name == styleAttr && elementData()->m_styleAttributeIsDirty)) {
393        ASSERT(isStyledElement());
394        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
395        return;
396    }
397#if ENABLE(SVG)
398    if (UNLIKELY(elementData()->m_animatedSVGAttributesAreDirty)) {
399        ASSERT(isSVGElement());
400        toSVGElement(this)->synchronizeAnimatedSVGAttribute(name);
401    }
402#endif
403}
404
405inline void Element::synchronizeAttribute(const AtomicString& localName) const
406{
407    // This version of synchronizeAttribute() is streamlined for the case where you don't have a full QualifiedName,
408    // e.g when called from DOM API.
409    if (!elementData())
410        return;
411    if (elementData()->m_styleAttributeIsDirty && equalPossiblyIgnoringCase(localName, styleAttr.localName(), shouldIgnoreAttributeCase(this))) {
412        ASSERT(isStyledElement());
413        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
414        return;
415    }
416#if ENABLE(SVG)
417    if (elementData()->m_animatedSVGAttributesAreDirty) {
418        // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
419        ASSERT(isSVGElement());
420        static_cast<const SVGElement*>(this)->synchronizeAnimatedSVGAttribute(QualifiedName(nullAtom, localName, nullAtom));
421    }
422#endif
423}
424
425const AtomicString& Element::getAttribute(const QualifiedName& name) const
426{
427    if (!elementData())
428        return nullAtom;
429    synchronizeAttribute(name);
430    if (const Attribute* attribute = getAttributeItem(name))
431        return attribute->value();
432    return nullAtom;
433}
434
435bool Element::isFocusable() const
436{
437    if (!inDocument() || !supportsFocus())
438        return false;
439
440    // Elements in canvas fallback content are not rendered, but they are allowed to be
441    // focusable as long as their canvas is displayed and visible.
442    if (isInCanvasSubtree()) {
443        const Element* e = this;
444        while (e && !e->hasLocalName(canvasTag))
445            e = e->parentElement();
446        ASSERT(e);
447        return e->renderer() && e->renderer()->style()->visibility() == VISIBLE;
448    }
449
450    if (renderer())
451        ASSERT(!renderer()->needsLayout());
452    else {
453        // If the node is in a display:none tree it might say it needs style recalc but
454        // the whole document is actually up to date.
455        ASSERT(!document()->childNeedsStyleRecalc());
456    }
457
458    // FIXME: Even if we are not visible, we might have a child that is visible.
459    // Hyatt wants to fix that some day with a "has visible content" flag or the like.
460    if (!renderer() || renderer()->style()->visibility() != VISIBLE)
461        return false;
462
463    return true;
464}
465
466bool Element::isUserActionElementInActiveChain() const
467{
468    ASSERT(isUserActionElement());
469    return document()->userActionElements().isInActiveChain(this);
470}
471
472bool Element::isUserActionElementActive() const
473{
474    ASSERT(isUserActionElement());
475    return document()->userActionElements().isActive(this);
476}
477
478bool Element::isUserActionElementFocused() const
479{
480    ASSERT(isUserActionElement());
481    return document()->userActionElements().isFocused(this);
482}
483
484bool Element::isUserActionElementHovered() const
485{
486    ASSERT(isUserActionElement());
487    return document()->userActionElements().isHovered(this);
488}
489
490void Element::setActive(bool flag, bool pause)
491{
492    if (flag == active())
493        return;
494
495    if (Document* document = this->document())
496        document->userActionElements().setActive(this, flag);
497
498    if (!renderer())
499        return;
500
501    bool reactsToPress = renderStyle()->affectedByActive() || childrenAffectedByActive();
502    if (reactsToPress)
503        setNeedsStyleRecalc();
504
505    if (renderer()->style()->hasAppearance() && renderer()->theme()->stateChanged(renderer(), PressedState))
506        reactsToPress = true;
507
508    // The rest of this function implements a feature that only works if the
509    // platform supports immediate invalidations on the ChromeClient, so bail if
510    // that isn't supported.
511    if (!document()->page()->chrome().client()->supportsImmediateInvalidation())
512        return;
513
514    if (reactsToPress && pause) {
515        // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes
516        // to repaint the "down" state of the control is about the same time as it would take to repaint the
517        // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you
518        // leave this method, it will be about that long before the flush of the up state happens again).
519#ifdef HAVE_FUNC_USLEEP
520        double startTime = currentTime();
521#endif
522
523        Document::updateStyleForAllDocuments();
524        // Do an immediate repaint.
525        if (renderer())
526            renderer()->repaint(true);
527
528        // FIXME: Come up with a less ridiculous way of doing this.
529#ifdef HAVE_FUNC_USLEEP
530        // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
531        double remainingTime = 0.1 - (currentTime() - startTime);
532        if (remainingTime > 0)
533            usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
534#endif
535    }
536}
537
538void Element::setFocus(bool flag)
539{
540    if (flag == focused())
541        return;
542
543    if (Document* document = this->document())
544        document->userActionElements().setFocused(this, flag);
545
546    setNeedsStyleRecalc();
547}
548
549void Element::setHovered(bool flag)
550{
551    if (flag == hovered())
552        return;
553
554    if (Document* document = this->document())
555        document->userActionElements().setHovered(this, flag);
556
557    if (!renderer()) {
558        // When setting hover to false, the style needs to be recalc'd even when
559        // there's no renderer (imagine setting display:none in the :hover class,
560        // if a nil renderer would prevent this element from recalculating its
561        // style, it would never go back to its normal style and remain
562        // stuck in its hovered style).
563        if (!flag)
564            setNeedsStyleRecalc();
565
566        return;
567    }
568
569    if (renderer()->style()->affectedByHover() || childrenAffectedByHover())
570        setNeedsStyleRecalc();
571
572    if (renderer()->style()->hasAppearance())
573        renderer()->theme()->stateChanged(renderer(), HoverState);
574}
575
576void Element::scrollIntoView(bool alignToTop)
577{
578    document()->updateLayoutIgnorePendingStylesheets();
579
580    if (!renderer())
581        return;
582
583    LayoutRect bounds = boundingBox();
584    // Align to the top / bottom and to the closest edge.
585    if (alignToTop)
586        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
587    else
588        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
589}
590
591void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
592{
593    document()->updateLayoutIgnorePendingStylesheets();
594
595    if (!renderer())
596        return;
597
598    LayoutRect bounds = boundingBox();
599    if (centerIfNeeded)
600        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
601    else
602        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
603}
604
605void Element::scrollByUnits(int units, ScrollGranularity granularity)
606{
607    document()->updateLayoutIgnorePendingStylesheets();
608
609    if (!renderer())
610        return;
611
612    if (!renderer()->hasOverflowClip())
613        return;
614
615    ScrollDirection direction = ScrollDown;
616    if (units < 0) {
617        direction = ScrollUp;
618        units = -units;
619    }
620    Node* stopNode = this;
621    toRenderBox(renderer())->scroll(direction, granularity, units, &stopNode);
622}
623
624void Element::scrollByLines(int lines)
625{
626    scrollByUnits(lines, ScrollByLine);
627}
628
629void Element::scrollByPages(int pages)
630{
631    scrollByUnits(pages, ScrollByPage);
632}
633
634static float localZoomForRenderer(RenderObject* renderer)
635{
636    // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
637    // other out, but the alternative is that we'd have to crawl up the whole render tree every
638    // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
639    float zoomFactor = 1;
640    if (renderer->style()->effectiveZoom() != 1) {
641        // Need to find the nearest enclosing RenderObject that set up
642        // a differing zoom, and then we divide our result by it to eliminate the zoom.
643        RenderObject* prev = renderer;
644        for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
645            if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
646                zoomFactor = prev->style()->zoom();
647                break;
648            }
649            prev = curr;
650        }
651        if (prev->isRenderView())
652            zoomFactor = prev->style()->zoom();
653    }
654    return zoomFactor;
655}
656
657static int adjustForLocalZoom(LayoutUnit value, RenderObject* renderer)
658{
659    float zoomFactor = localZoomForRenderer(renderer);
660    if (zoomFactor == 1)
661        return value;
662#if ENABLE(SUBPIXEL_LAYOUT)
663    return lroundf(value / zoomFactor);
664#else
665    // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
666    if (zoomFactor > 1)
667        value++;
668    return static_cast<int>(value / zoomFactor);
669#endif
670}
671
672int Element::offsetLeft()
673{
674    document()->updateLayoutIgnorePendingStylesheets();
675    if (RenderBoxModelObject* renderer = renderBoxModelObject())
676        return adjustForLocalZoom(renderer->pixelSnappedOffsetLeft(), renderer);
677    return 0;
678}
679
680int Element::offsetTop()
681{
682    document()->updateLayoutIgnorePendingStylesheets();
683    if (RenderBoxModelObject* renderer = renderBoxModelObject())
684        return adjustForLocalZoom(renderer->pixelSnappedOffsetTop(), renderer);
685    return 0;
686}
687
688int Element::offsetWidth()
689{
690    document()->updateLayoutIgnorePendingStylesheets();
691    if (RenderBoxModelObject* renderer = renderBoxModelObject())
692#if ENABLE(SUBPIXEL_LAYOUT)
693        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), renderer).round();
694#else
695        return adjustForAbsoluteZoom(renderer->pixelSnappedOffsetWidth(), renderer);
696#endif
697    return 0;
698}
699
700int Element::offsetHeight()
701{
702    document()->updateLayoutIgnorePendingStylesheets();
703    if (RenderBoxModelObject* renderer = renderBoxModelObject())
704#if ENABLE(SUBPIXEL_LAYOUT)
705        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), renderer).round();
706#else
707        return adjustForAbsoluteZoom(renderer->pixelSnappedOffsetHeight(), renderer);
708#endif
709    return 0;
710}
711
712Element* Element::bindingsOffsetParent()
713{
714    Element* element = offsetParent();
715    if (!element || !element->isInShadowTree())
716        return element;
717    return element->containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot ? 0 : element;
718}
719
720Element* Element::offsetParent()
721{
722    document()->updateLayoutIgnorePendingStylesheets();
723    if (RenderObject* renderer = this->renderer()) {
724        if (RenderObject* offsetParent = renderer->offsetParent())
725            return toElement(offsetParent->node());
726    }
727    return 0;
728}
729
730int Element::clientLeft()
731{
732    document()->updateLayoutIgnorePendingStylesheets();
733
734    if (RenderBox* renderer = renderBox())
735        return adjustForAbsoluteZoom(roundToInt(renderer->clientLeft()), renderer);
736    return 0;
737}
738
739int Element::clientTop()
740{
741    document()->updateLayoutIgnorePendingStylesheets();
742
743    if (RenderBox* renderer = renderBox())
744        return adjustForAbsoluteZoom(roundToInt(renderer->clientTop()), renderer);
745    return 0;
746}
747
748int Element::clientWidth()
749{
750    document()->updateLayoutIgnorePendingStylesheets();
751
752    // When in strict mode, clientWidth for the document element should return the width of the containing frame.
753    // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
754    bool inQuirksMode = document()->inQuirksMode();
755    if ((!inQuirksMode && document()->documentElement() == this) ||
756        (inQuirksMode && isHTMLElement() && document()->body() == this)) {
757        if (FrameView* view = document()->view()) {
758            if (RenderView* renderView = document()->renderView())
759                return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
760        }
761    }
762
763    if (RenderBox* renderer = renderBox())
764#if ENABLE(SUBPIXEL_LAYOUT)
765        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientWidth(), renderer).round();
766#else
767        return adjustForAbsoluteZoom(renderer->pixelSnappedClientWidth(), renderer);
768#endif
769    return 0;
770}
771
772int Element::clientHeight()
773{
774    document()->updateLayoutIgnorePendingStylesheets();
775
776    // When in strict mode, clientHeight for the document element should return the height of the containing frame.
777    // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
778    bool inQuirksMode = document()->inQuirksMode();
779
780    if ((!inQuirksMode && document()->documentElement() == this) ||
781        (inQuirksMode && isHTMLElement() && document()->body() == this)) {
782        if (FrameView* view = document()->view()) {
783            if (RenderView* renderView = document()->renderView())
784                return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
785        }
786    }
787
788    if (RenderBox* renderer = renderBox())
789#if ENABLE(SUBPIXEL_LAYOUT)
790        return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientHeight(), renderer).round();
791#else
792        return adjustForAbsoluteZoom(renderer->pixelSnappedClientHeight(), renderer);
793#endif
794    return 0;
795}
796
797int Element::scrollLeft()
798{
799    document()->updateLayoutIgnorePendingStylesheets();
800    if (RenderBox* rend = renderBox())
801        return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
802    return 0;
803}
804
805int Element::scrollTop()
806{
807    document()->updateLayoutIgnorePendingStylesheets();
808    if (RenderBox* rend = renderBox())
809        return adjustForAbsoluteZoom(rend->scrollTop(), rend);
810    return 0;
811}
812
813void Element::setScrollLeft(int newLeft)
814{
815    document()->updateLayoutIgnorePendingStylesheets();
816    if (RenderBox* rend = renderBox())
817        rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
818}
819
820void Element::setScrollTop(int newTop)
821{
822    document()->updateLayoutIgnorePendingStylesheets();
823    if (RenderBox* rend = renderBox())
824        rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
825}
826
827int Element::scrollWidth()
828{
829    document()->updateLayoutIgnorePendingStylesheets();
830    if (RenderBox* rend = renderBox())
831        return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
832    return 0;
833}
834
835int Element::scrollHeight()
836{
837    document()->updateLayoutIgnorePendingStylesheets();
838    if (RenderBox* rend = renderBox())
839        return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
840    return 0;
841}
842
843IntRect Element::boundsInRootViewSpace()
844{
845    document()->updateLayoutIgnorePendingStylesheets();
846
847    FrameView* view = document()->view();
848    if (!view)
849        return IntRect();
850
851    Vector<FloatQuad> quads;
852#if ENABLE(SVG)
853    if (isSVGElement() && renderer()) {
854        // Get the bounding rectangle from the SVG model.
855        SVGElement* svgElement = toSVGElement(this);
856        FloatRect localRect;
857        if (svgElement->getBoundingBox(localRect))
858            quads.append(renderer()->localToAbsoluteQuad(localRect));
859    } else
860#endif
861    {
862        // Get the bounding rectangle from the box model.
863        if (renderBoxModelObject())
864            renderBoxModelObject()->absoluteQuads(quads);
865    }
866
867    if (quads.isEmpty())
868        return IntRect();
869
870    IntRect result = quads[0].enclosingBoundingBox();
871    for (size_t i = 1; i < quads.size(); ++i)
872        result.unite(quads[i].enclosingBoundingBox());
873
874    result = view->contentsToRootView(result);
875    return result;
876}
877
878PassRefPtr<ClientRectList> Element::getClientRects()
879{
880    document()->updateLayoutIgnorePendingStylesheets();
881
882    RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
883    if (!renderBoxModelObject)
884        return ClientRectList::create();
885
886    // FIXME: Handle SVG elements.
887    // FIXME: Handle table/inline-table with a caption.
888
889    Vector<FloatQuad> quads;
890    renderBoxModelObject->absoluteQuads(quads);
891    document()->adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(quads, renderBoxModelObject);
892    return ClientRectList::create(quads);
893}
894
895PassRefPtr<ClientRect> Element::getBoundingClientRect()
896{
897    document()->updateLayoutIgnorePendingStylesheets();
898
899    Vector<FloatQuad> quads;
900#if ENABLE(SVG)
901    if (isSVGElement() && renderer() && !renderer()->isSVGRoot()) {
902        // Get the bounding rectangle from the SVG model.
903        SVGElement* svgElement = toSVGElement(this);
904        FloatRect localRect;
905        if (svgElement->getBoundingBox(localRect))
906            quads.append(renderer()->localToAbsoluteQuad(localRect));
907    } else
908#endif
909    {
910        // Get the bounding rectangle from the box model.
911        if (renderBoxModelObject())
912            renderBoxModelObject()->absoluteQuads(quads);
913    }
914
915    if (quads.isEmpty())
916        return ClientRect::create();
917
918    FloatRect result = quads[0].boundingBox();
919    for (size_t i = 1; i < quads.size(); ++i)
920        result.unite(quads[i].boundingBox());
921
922    document()->adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(result, renderer());
923    return ClientRect::create(result);
924}
925
926IntRect Element::screenRect() const
927{
928    if (!renderer())
929        return IntRect();
930    // FIXME: this should probably respect transforms
931    return document()->view()->contentsToScreen(renderer()->absoluteBoundingBoxRectIgnoringTransforms());
932}
933
934const AtomicString& Element::getAttribute(const AtomicString& localName) const
935{
936    if (!elementData())
937        return nullAtom;
938    synchronizeAttribute(localName);
939    if (const Attribute* attribute = elementData()->getAttributeItem(localName, shouldIgnoreAttributeCase(this)))
940        return attribute->value();
941    return nullAtom;
942}
943
944const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
945{
946    return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
947}
948
949void Element::setAttribute(const AtomicString& localName, const AtomicString& value, ExceptionCode& ec)
950{
951    if (!Document::isValidName(localName)) {
952        ec = INVALID_CHARACTER_ERR;
953        return;
954    }
955
956    synchronizeAttribute(localName);
957    const AtomicString& caseAdjustedLocalName = shouldIgnoreAttributeCase(this) ? localName.lower() : localName;
958
959    unsigned index = elementData() ? elementData()->getAttributeItemIndex(caseAdjustedLocalName, false) : ElementData::attributeNotFound;
960    const QualifiedName& qName = index != ElementData::attributeNotFound ? attributeItem(index)->name() : QualifiedName(nullAtom, caseAdjustedLocalName, nullAtom);
961    setAttributeInternal(index, qName, value, NotInSynchronizationOfLazyAttribute);
962}
963
964void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
965{
966    synchronizeAttribute(name);
967    unsigned index = elementData() ? elementData()->getAttributeItemIndex(name) : ElementData::attributeNotFound;
968    setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
969}
970
971void Element::setSynchronizedLazyAttribute(const QualifiedName& name, const AtomicString& value)
972{
973    unsigned index = elementData() ? elementData()->getAttributeItemIndex(name) : ElementData::attributeNotFound;
974    setAttributeInternal(index, name, value, InSynchronizationOfLazyAttribute);
975}
976
977inline void Element::setAttributeInternal(unsigned index, const QualifiedName& name, const AtomicString& newValue, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
978{
979    if (newValue.isNull()) {
980        if (index != ElementData::attributeNotFound)
981            removeAttributeInternal(index, inSynchronizationOfLazyAttribute);
982        return;
983    }
984
985    if (index == ElementData::attributeNotFound) {
986        addAttributeInternal(name, newValue, inSynchronizationOfLazyAttribute);
987        return;
988    }
989
990    if (!inSynchronizationOfLazyAttribute)
991        willModifyAttribute(name, attributeItem(index)->value(), newValue);
992
993    if (newValue != attributeItem(index)->value()) {
994        // If there is an Attr node hooked to this attribute, the Attr::setValue() call below
995        // will write into the ElementData.
996        // FIXME: Refactor this so it makes some sense.
997        if (RefPtr<Attr> attrNode = inSynchronizationOfLazyAttribute ? 0 : attrIfExists(name))
998            attrNode->setValue(newValue);
999        else
1000            ensureUniqueElementData()->attributeItem(index)->setValue(newValue);
1001    }
1002
1003    if (!inSynchronizationOfLazyAttribute)
1004        didModifyAttribute(name, newValue);
1005}
1006
1007static inline AtomicString makeIdForStyleResolution(const AtomicString& value, bool inQuirksMode)
1008{
1009    if (inQuirksMode)
1010        return value.lower();
1011    return value;
1012}
1013
1014static bool checkNeedsStyleInvalidationForIdChange(const AtomicString& oldId, const AtomicString& newId, StyleResolver* styleResolver)
1015{
1016    ASSERT(newId != oldId);
1017    if (!oldId.isEmpty() && styleResolver->hasSelectorForId(oldId))
1018        return true;
1019    if (!newId.isEmpty() && styleResolver->hasSelectorForId(newId))
1020        return true;
1021    return false;
1022}
1023
1024void Element::attributeChanged(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason)
1025{
1026    parseAttribute(name, newValue);
1027
1028    document()->incDOMTreeVersion();
1029
1030    StyleResolver* styleResolver = document()->styleResolverIfExists();
1031    bool testShouldInvalidateStyle = attached() && styleResolver && styleChangeType() < FullStyleChange;
1032    bool shouldInvalidateStyle = false;
1033
1034    if (isIdAttributeName(name)) {
1035        AtomicString oldId = elementData()->idForStyleResolution();
1036        AtomicString newId = makeIdForStyleResolution(newValue, document()->inQuirksMode());
1037        if (newId != oldId) {
1038            elementData()->setIdForStyleResolution(newId);
1039            shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver);
1040        }
1041    } else if (name == classAttr)
1042        classAttributeChanged(newValue);
1043    else if (name == HTMLNames::nameAttr)
1044        elementData()->m_hasNameAttribute = !newValue.isNull();
1045    else if (name == HTMLNames::pseudoAttr)
1046        shouldInvalidateStyle |= testShouldInvalidateStyle && isInShadowTree();
1047
1048
1049    invalidateNodeListCachesInAncestors(&name, this);
1050
1051    // If there is currently no StyleResolver, we can't be sure that this attribute change won't affect style.
1052    shouldInvalidateStyle |= !styleResolver;
1053
1054    if (shouldInvalidateStyle)
1055        setNeedsStyleRecalc();
1056
1057    if (AXObjectCache* cache = document()->existingAXObjectCache())
1058        cache->handleAttributeChanged(name, this);
1059}
1060
1061inline void Element::attributeChangedFromParserOrByCloning(const QualifiedName& name, const AtomicString& newValue, AttributeModificationReason reason)
1062{
1063#if ENABLE(CUSTOM_ELEMENTS)
1064    if (name == isAttr) {
1065        if (CustomElementRegistry* registry = document()->registry())
1066            registry->didGiveTypeExtension(this);
1067    }
1068#endif
1069    attributeChanged(name, newValue, reason);
1070}
1071
1072template <typename CharacterType>
1073static inline bool classStringHasClassName(const CharacterType* characters, unsigned length)
1074{
1075    ASSERT(length > 0);
1076
1077    unsigned i = 0;
1078    do {
1079        if (isNotHTMLSpace(characters[i]))
1080            break;
1081        ++i;
1082    } while (i < length);
1083
1084    return i < length;
1085}
1086
1087static inline bool classStringHasClassName(const AtomicString& newClassString)
1088{
1089    unsigned length = newClassString.length();
1090
1091    if (!length)
1092        return false;
1093
1094    if (newClassString.is8Bit())
1095        return classStringHasClassName(newClassString.characters8(), length);
1096    return classStringHasClassName(newClassString.characters16(), length);
1097}
1098
1099template<typename Checker>
1100static bool checkSelectorForClassChange(const SpaceSplitString& changedClasses, const Checker& checker)
1101{
1102    unsigned changedSize = changedClasses.size();
1103    for (unsigned i = 0; i < changedSize; ++i) {
1104        if (checker.hasSelectorForClass(changedClasses[i]))
1105            return true;
1106    }
1107    return false;
1108}
1109
1110template<typename Checker>
1111static bool checkSelectorForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, const Checker& checker)
1112{
1113    unsigned oldSize = oldClasses.size();
1114    if (!oldSize)
1115        return checkSelectorForClassChange(newClasses, checker);
1116    BitVector remainingClassBits;
1117    remainingClassBits.ensureSize(oldSize);
1118    // Class vectors tend to be very short. This is faster than using a hash table.
1119    unsigned newSize = newClasses.size();
1120    for (unsigned i = 0; i < newSize; ++i) {
1121        for (unsigned j = 0; j < oldSize; ++j) {
1122            if (newClasses[i] == oldClasses[j]) {
1123                remainingClassBits.quickSet(j);
1124                continue;
1125            }
1126        }
1127        if (checker.hasSelectorForClass(newClasses[i]))
1128            return true;
1129    }
1130    for (unsigned i = 0; i < oldSize; ++i) {
1131        // If the bit is not set the the corresponding class has been removed.
1132        if (remainingClassBits.quickGet(i))
1133            continue;
1134        if (checker.hasSelectorForClass(oldClasses[i]))
1135            return true;
1136    }
1137    return false;
1138}
1139
1140void Element::classAttributeChanged(const AtomicString& newClassString)
1141{
1142    StyleResolver* styleResolver = document()->styleResolverIfExists();
1143    bool testShouldInvalidateStyle = attached() && styleResolver && styleChangeType() < FullStyleChange;
1144    bool shouldInvalidateStyle = false;
1145
1146    if (classStringHasClassName(newClassString)) {
1147        const bool shouldFoldCase = document()->inQuirksMode();
1148        const SpaceSplitString oldClasses = elementData()->classNames();
1149        elementData()->setClass(newClassString, shouldFoldCase);
1150        const SpaceSplitString& newClasses = elementData()->classNames();
1151        shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForClassChange(oldClasses, newClasses, *styleResolver);
1152    } else {
1153        const SpaceSplitString& oldClasses = elementData()->classNames();
1154        shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForClassChange(oldClasses, *styleResolver);
1155        elementData()->clearClass();
1156    }
1157
1158    if (hasRareData())
1159        elementRareData()->clearClassListValueForQuirksMode();
1160
1161    if (shouldInvalidateStyle)
1162        setNeedsStyleRecalc();
1163}
1164
1165// Returns true is the given attribute is an event handler.
1166// We consider an event handler any attribute that begins with "on".
1167// It is a simple solution that has the advantage of not requiring any
1168// code or configuration change if a new event handler is defined.
1169
1170static inline bool isEventHandlerAttribute(const Attribute& attribute)
1171{
1172    return attribute.name().namespaceURI().isNull() && attribute.name().localName().startsWith("on");
1173}
1174
1175bool Element::isJavaScriptURLAttribute(const Attribute& attribute) const
1176{
1177    return isURLAttribute(attribute) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(attribute.value()));
1178}
1179
1180void Element::stripScriptingAttributes(Vector<Attribute>& attributeVector) const
1181{
1182    size_t destination = 0;
1183    for (size_t source = 0; source < attributeVector.size(); ++source) {
1184        if (isEventHandlerAttribute(attributeVector[source])
1185            || isJavaScriptURLAttribute(attributeVector[source])
1186            || isHTMLContentAttribute(attributeVector[source]))
1187            continue;
1188
1189        if (source != destination)
1190            attributeVector[destination] = attributeVector[source];
1191
1192        ++destination;
1193    }
1194    attributeVector.shrink(destination);
1195}
1196
1197void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
1198{
1199    ASSERT(!inDocument());
1200    ASSERT(!parentNode());
1201    ASSERT(!m_elementData);
1202
1203    if (attributeVector.isEmpty())
1204        return;
1205
1206    if (document() && document()->sharedObjectPool())
1207        m_elementData = document()->sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector);
1208    else
1209        m_elementData = ShareableElementData::createWithAttributes(attributeVector);
1210
1211    // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData.
1212    for (unsigned i = 0; i < attributeVector.size(); ++i)
1213        attributeChangedFromParserOrByCloning(attributeVector[i].name(), attributeVector[i].value(), ModifiedDirectly);
1214}
1215
1216bool Element::hasAttributes() const
1217{
1218    synchronizeAllAttributes();
1219    return elementData() && elementData()->length();
1220}
1221
1222bool Element::hasEquivalentAttributes(const Element* other) const
1223{
1224    synchronizeAllAttributes();
1225    other->synchronizeAllAttributes();
1226    if (elementData() == other->elementData())
1227        return true;
1228    if (elementData())
1229        return elementData()->isEquivalent(other->elementData());
1230    if (other->elementData())
1231        return other->elementData()->isEquivalent(elementData());
1232    return true;
1233}
1234
1235String Element::nodeName() const
1236{
1237    return m_tagName.toString();
1238}
1239
1240String Element::nodeNamePreservingCase() const
1241{
1242    return m_tagName.toString();
1243}
1244
1245void Element::setPrefix(const AtomicString& prefix, ExceptionCode& ec)
1246{
1247    ec = 0;
1248    checkSetPrefix(prefix, ec);
1249    if (ec)
1250        return;
1251
1252    m_tagName.setPrefix(prefix.isEmpty() ? AtomicString() : prefix);
1253}
1254
1255KURL Element::baseURI() const
1256{
1257    const AtomicString& baseAttribute = getAttribute(baseAttr);
1258    KURL base(KURL(), baseAttribute);
1259    if (!base.protocol().isEmpty())
1260        return base;
1261
1262    ContainerNode* parent = parentNode();
1263    if (!parent)
1264        return base;
1265
1266    const KURL& parentBase = parent->baseURI();
1267    if (parentBase.isNull())
1268        return base;
1269
1270    return KURL(parentBase, baseAttribute);
1271}
1272
1273const AtomicString& Element::imageSourceURL() const
1274{
1275    return getAttribute(srcAttr);
1276}
1277
1278bool Element::rendererIsNeeded(const NodeRenderingContext& context)
1279{
1280    return context.style()->display() != NONE;
1281}
1282
1283RenderObject* Element::createRenderer(RenderArena*, RenderStyle* style)
1284{
1285    return RenderObject::createObject(this, style);
1286}
1287
1288bool Element::isDisabledFormControl() const
1289{
1290#if ENABLE(DIALOG_ELEMENT)
1291    // FIXME: disabled and inert are separate concepts in the spec, but now we treat them as the same.
1292    // For example, an inert, non-disabled form control should not be grayed out.
1293    if (isInert())
1294        return true;
1295#endif
1296    return false;
1297}
1298
1299#if ENABLE(DIALOG_ELEMENT)
1300bool Element::isInert() const
1301{
1302    Element* dialog = document()->activeModalDialog();
1303    return dialog && !containsIncludingShadowDOM(dialog) && !dialog->containsIncludingShadowDOM(this);
1304}
1305#endif
1306
1307Node::InsertionNotificationRequest Element::insertedInto(ContainerNode* insertionPoint)
1308{
1309    bool wasInDocument = inDocument();
1310    // need to do superclass processing first so inDocument() is true
1311    // by the time we reach updateId
1312    ContainerNode::insertedInto(insertionPoint);
1313    ASSERT(!wasInDocument || inDocument());
1314
1315#if ENABLE(FULLSCREEN_API)
1316    if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
1317        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
1318#endif
1319
1320    if (Element* before = pseudoElement(BEFORE))
1321        before->insertedInto(insertionPoint);
1322
1323    if (Element* after = pseudoElement(AFTER))
1324        after->insertedInto(insertionPoint);
1325
1326    if (!insertionPoint->isInTreeScope())
1327        return InsertionDone;
1328
1329    if (hasRareData())
1330        elementRareData()->clearClassListValueForQuirksMode();
1331
1332    TreeScope* newScope = insertionPoint->treeScope();
1333    HTMLDocument* newDocument = !wasInDocument && inDocument() && newScope->documentScope()->isHTMLDocument() ? toHTMLDocument(newScope->documentScope()) : 0;
1334    if (newScope != treeScope())
1335        newScope = 0;
1336
1337    const AtomicString& idValue = getIdAttribute();
1338    if (!idValue.isNull()) {
1339        if (newScope)
1340            updateIdForTreeScope(newScope, nullAtom, idValue);
1341        if (newDocument)
1342            updateIdForDocument(newDocument, nullAtom, idValue, AlwaysUpdateHTMLDocumentNamedItemMaps);
1343    }
1344
1345    const AtomicString& nameValue = getNameAttribute();
1346    if (!nameValue.isNull()) {
1347        if (newScope)
1348            updateNameForTreeScope(newScope, nullAtom, nameValue);
1349        if (newDocument)
1350            updateNameForDocument(newDocument, nullAtom, nameValue);
1351    }
1352
1353    if (newScope && hasTagName(labelTag)) {
1354        if (newScope->shouldCacheLabelsByForAttribute())
1355            updateLabel(newScope, nullAtom, fastGetAttribute(forAttr));
1356    }
1357
1358    return InsertionDone;
1359}
1360
1361void Element::removedFrom(ContainerNode* insertionPoint)
1362{
1363#if ENABLE(SVG)
1364    bool wasInDocument = insertionPoint->document();
1365#endif
1366
1367    if (Element* before = pseudoElement(BEFORE))
1368        before->removedFrom(insertionPoint);
1369
1370    if (Element* after = pseudoElement(AFTER))
1371        after->removedFrom(insertionPoint);
1372
1373#if ENABLE(DIALOG_ELEMENT)
1374    document()->removeFromTopLayer(this);
1375#endif
1376#if ENABLE(FULLSCREEN_API)
1377    if (containsFullScreenElement())
1378        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
1379#endif
1380#if ENABLE(POINTER_LOCK)
1381    if (document()->page())
1382        document()->page()->pointerLockController()->elementRemoved(this);
1383#endif
1384
1385    setSavedLayerScrollOffset(IntSize());
1386
1387    if (insertionPoint->isInTreeScope()) {
1388        TreeScope* oldScope = insertionPoint->treeScope();
1389        HTMLDocument* oldDocument = inDocument() && oldScope->documentScope()->isHTMLDocument() ? toHTMLDocument(oldScope->documentScope()) : 0;
1390        if (oldScope != treeScope() || !isInTreeScope())
1391            oldScope = 0;
1392
1393        const AtomicString& idValue = getIdAttribute();
1394        if (!idValue.isNull()) {
1395            if (oldScope)
1396                updateIdForTreeScope(oldScope, idValue, nullAtom);
1397            if (oldDocument)
1398                updateIdForDocument(oldDocument, idValue, nullAtom, AlwaysUpdateHTMLDocumentNamedItemMaps);
1399        }
1400
1401        const AtomicString& nameValue = getNameAttribute();
1402        if (!nameValue.isNull()) {
1403            if (oldScope)
1404                updateNameForTreeScope(oldScope, nameValue, nullAtom);
1405            if (oldDocument)
1406                updateNameForDocument(oldDocument, nameValue, nullAtom);
1407        }
1408
1409        if (oldScope && hasTagName(labelTag)) {
1410            if (oldScope->shouldCacheLabelsByForAttribute())
1411                updateLabel(oldScope, fastGetAttribute(forAttr), nullAtom);
1412        }
1413    }
1414
1415    ContainerNode::removedFrom(insertionPoint);
1416#if ENABLE(SVG)
1417    if (wasInDocument && hasPendingResources())
1418        document()->accessSVGExtensions()->removeElementFromPendingResources(this);
1419#endif
1420}
1421
1422void Element::createRendererIfNeeded(const AttachContext& context)
1423{
1424    NodeRenderingContext(this, context).createRendererForElementIfNeeded();
1425}
1426
1427void Element::attach(const AttachContext& context)
1428{
1429    PostAttachCallbackDisabler callbackDisabler(this);
1430    StyleResolverParentPusher parentPusher(this);
1431    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
1432
1433    createRendererIfNeeded(context);
1434
1435    if (parentElement() && parentElement()->isInCanvasSubtree())
1436        setIsInCanvasSubtree(true);
1437
1438    updatePseudoElement(BEFORE);
1439
1440    // When a shadow root exists, it does the work of attaching the children.
1441    if (ElementShadow* shadow = this->shadow()) {
1442        parentPusher.push();
1443        shadow->attach();
1444    } else if (firstChild())
1445        parentPusher.push();
1446
1447    ContainerNode::attach(context);
1448
1449    updatePseudoElement(AFTER);
1450
1451    if (hasRareData()) {
1452        ElementRareData* data = elementRareData();
1453        if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
1454            if (isFocusable() && document()->focusedElement() == this)
1455                document()->updateFocusAppearanceSoon(false /* don't restore selection */);
1456            data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1457        }
1458    }
1459}
1460
1461void Element::unregisterNamedFlowContentNode()
1462{
1463    if (document()->cssRegionsEnabled() && inNamedFlow() && document()->renderView())
1464        document()->renderView()->flowThreadController()->unregisterNamedFlowContentNode(this);
1465}
1466
1467void Element::detach(const AttachContext& context)
1468{
1469    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
1470    unregisterNamedFlowContentNode();
1471    cancelFocusAppearanceUpdate();
1472    if (hasRareData()) {
1473        ElementRareData* data = elementRareData();
1474        data->setPseudoElement(BEFORE, 0);
1475        data->setPseudoElement(AFTER, 0);
1476        data->setIsInCanvasSubtree(false);
1477        data->resetComputedStyle();
1478        data->resetDynamicRestyleObservations();
1479        data->setIsInsideRegion(false);
1480    }
1481
1482    if (ElementShadow* shadow = this->shadow()) {
1483        detachChildrenIfNeeded();
1484        shadow->detach();
1485    }
1486
1487    // Do not remove the element's hovered and active status
1488    // if performing a reattach.
1489    if (!context.performingReattach) {
1490        if (isUserActionElement()) {
1491            if (hovered())
1492                document()->hoveredElementDidDetach(this);
1493            if (inActiveChain())
1494                document()->elementInActiveChainDidDetach(this);
1495            document()->userActionElements().didDetach(this);
1496        }
1497    }
1498
1499    ContainerNode::detach(context);
1500}
1501
1502bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
1503{
1504    ASSERT(currentStyle == renderStyle());
1505    ASSERT(renderer());
1506
1507    if (!currentStyle)
1508        return false;
1509
1510    const PseudoStyleCache* pseudoStyleCache = currentStyle->cachedPseudoStyles();
1511    if (!pseudoStyleCache)
1512        return false;
1513
1514    size_t cacheSize = pseudoStyleCache->size();
1515    for (size_t i = 0; i < cacheSize; ++i) {
1516        RefPtr<RenderStyle> newPseudoStyle;
1517        PseudoId pseudoId = pseudoStyleCache->at(i)->styleType();
1518        if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
1519            newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
1520        else
1521            newPseudoStyle = renderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
1522        if (!newPseudoStyle)
1523            return true;
1524        if (*newPseudoStyle != *pseudoStyleCache->at(i)) {
1525            if (pseudoId < FIRST_INTERNAL_PSEUDOID)
1526                newStyle->setHasPseudoStyle(pseudoId);
1527            newStyle->addCachedPseudoStyle(newPseudoStyle);
1528            if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
1529                // FIXME: We should do an actual diff to determine whether a repaint vs. layout
1530                // is needed, but for now just assume a layout will be required.  The diff code
1531                // in RenderObject::setStyle would need to be factored out so that it could be reused.
1532                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
1533            }
1534            return true;
1535        }
1536    }
1537    return false;
1538}
1539
1540PassRefPtr<RenderStyle> Element::styleForRenderer()
1541{
1542    if (hasCustomStyleCallbacks()) {
1543        if (RefPtr<RenderStyle> style = customStyleForRenderer())
1544            return style.release();
1545    }
1546
1547    return document()->ensureStyleResolver()->styleForElement(this);
1548}
1549
1550void Element::recalcStyle(StyleChange change)
1551{
1552    if (hasCustomStyleCallbacks()) {
1553        if (!willRecalcStyle(change))
1554            return;
1555    }
1556
1557    // Ref currentStyle in case it would otherwise be deleted when setting the new style in the renderer.
1558    RefPtr<RenderStyle> currentStyle(renderStyle());
1559    bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
1560    bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
1561    bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
1562
1563    if ((change > NoChange || needsStyleRecalc())) {
1564        if (hasRareData())
1565            elementRareData()->resetComputedStyle();
1566    }
1567    if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
1568        StyleChange localChange = Detach;
1569        RefPtr<RenderStyle> newStyle;
1570        if (currentStyle) {
1571            newStyle = styleForRenderer();
1572            localChange = Node::diff(currentStyle.get(), newStyle.get(), document());
1573        }
1574        if (localChange == Detach) {
1575            AttachContext reattachContext;
1576            reattachContext.resolvedStyle = newStyle.get();
1577            reattach(reattachContext);
1578
1579            // attach recalculates the style for all children. No need to do it twice.
1580            clearNeedsStyleRecalc();
1581            clearChildNeedsStyleRecalc();
1582
1583            if (hasCustomStyleCallbacks())
1584                didRecalcStyle(change);
1585            return;
1586        }
1587
1588        if (RenderObject* renderer = this->renderer()) {
1589            if (localChange != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer->requiresForcedStyleRecalcPropagation()) || styleChangeType() == SyntheticStyleChange)
1590                renderer->setAnimatableStyle(newStyle.get());
1591            else if (needsStyleRecalc()) {
1592                // Although no change occurred, we use the new style so that the cousin style sharing code won't get
1593                // fooled into believing this style is the same.
1594                renderer->setStyleInternal(newStyle.get());
1595            }
1596        }
1597
1598        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
1599        // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
1600        if (document()->styleSheetCollection()->usesRemUnits() && document()->documentElement() == this && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
1601            // Cached RenderStyles may depend on the re units.
1602            if (StyleResolver* styleResolver = document()->styleResolverIfExists())
1603                styleResolver->invalidateMatchedPropertiesCache();
1604            change = Force;
1605        }
1606
1607        if (change != Force) {
1608            if (styleChangeType() >= FullStyleChange)
1609                change = Force;
1610            else
1611                change = localChange;
1612        }
1613    }
1614    StyleResolverParentPusher parentPusher(this);
1615
1616    // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
1617    if (ElementShadow* shadow = this->shadow()) {
1618        if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) {
1619            parentPusher.push();
1620            shadow->recalcStyle(change);
1621        }
1622    }
1623
1624    updatePseudoElement(BEFORE, change);
1625
1626    // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
1627    // For now we will just worry about the common case, since it's a lot trickier to get the second case right
1628    // without doing way too much re-resolution.
1629    bool forceCheckOfNextElementSibling = false;
1630    bool forceCheckOfAnyElementSibling = false;
1631    for (Node *n = firstChild(); n; n = n->nextSibling()) {
1632        if (n->isTextNode()) {
1633            toText(n)->recalcTextStyle(change);
1634            continue;
1635        }
1636        if (!n->isElementNode())
1637            continue;
1638        Element* element = toElement(n);
1639        bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() == FullStyleChange;
1640        if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
1641            element->setNeedsStyleRecalc();
1642        if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) {
1643            parentPusher.push();
1644            element->recalcStyle(change);
1645        }
1646        forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
1647        forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
1648    }
1649
1650    updatePseudoElement(AFTER, change);
1651
1652    clearNeedsStyleRecalc();
1653    clearChildNeedsStyleRecalc();
1654
1655    if (hasCustomStyleCallbacks())
1656        didRecalcStyle(change);
1657}
1658
1659ElementShadow* Element::shadow() const
1660{
1661    return hasRareData() ? elementRareData()->shadow() : 0;
1662}
1663
1664ElementShadow* Element::ensureShadow()
1665{
1666    return ensureElementRareData()->ensureShadow();
1667}
1668
1669void Element::didAffectSelector(AffectedSelectorMask)
1670{
1671    setNeedsStyleRecalc();
1672}
1673
1674PassRefPtr<ShadowRoot> Element::createShadowRoot(ExceptionCode& ec)
1675{
1676    if (alwaysCreateUserAgentShadowRoot())
1677        ensureUserAgentShadowRoot();
1678
1679#if ENABLE(SHADOW_DOM)
1680    if (RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
1681        return ensureShadow()->addShadowRoot(this, ShadowRoot::AuthorShadowRoot);
1682#endif
1683
1684    // Since some elements recreates shadow root dynamically, multiple shadow
1685    // subtrees won't work well in that element. Until they are fixed, we disable
1686    // adding author shadow root for them.
1687    if (!areAuthorShadowsAllowed()) {
1688        ec = HIERARCHY_REQUEST_ERR;
1689        return 0;
1690    }
1691    return ensureShadow()->addShadowRoot(this, ShadowRoot::AuthorShadowRoot);
1692}
1693
1694ShadowRoot* Element::authorShadowRoot() const
1695{
1696    ElementShadow* elementShadow = shadow();
1697    if (!elementShadow)
1698        return 0;
1699    ShadowRoot* shadowRoot = elementShadow->shadowRoot();
1700    if (shadowRoot->type() == ShadowRoot::AuthorShadowRoot)
1701        return shadowRoot;
1702    return 0;
1703}
1704
1705ShadowRoot* Element::userAgentShadowRoot() const
1706{
1707    if (ElementShadow* elementShadow = shadow()) {
1708        if (ShadowRoot* shadowRoot = elementShadow->shadowRoot()) {
1709            ASSERT(shadowRoot->type() == ShadowRoot::UserAgentShadowRoot);
1710            return shadowRoot;
1711        }
1712    }
1713
1714    return 0;
1715}
1716
1717ShadowRoot* Element::ensureUserAgentShadowRoot()
1718{
1719    ShadowRoot* shadowRoot = userAgentShadowRoot();
1720    if (!shadowRoot) {
1721        shadowRoot = ensureShadow()->addShadowRoot(this, ShadowRoot::UserAgentShadowRoot);
1722        didAddUserAgentShadowRoot(shadowRoot);
1723    }
1724    return shadowRoot;
1725}
1726
1727const AtomicString& Element::shadowPseudoId() const
1728{
1729    return pseudo();
1730}
1731
1732bool Element::childTypeAllowed(NodeType type) const
1733{
1734    switch (type) {
1735    case ELEMENT_NODE:
1736    case TEXT_NODE:
1737    case COMMENT_NODE:
1738    case PROCESSING_INSTRUCTION_NODE:
1739    case CDATA_SECTION_NODE:
1740    case ENTITY_REFERENCE_NODE:
1741        return true;
1742    default:
1743        break;
1744    }
1745    return false;
1746}
1747
1748static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
1749{
1750    if (!style && !element->styleAffectedByEmpty())
1751        return;
1752
1753    if (!style || (element->styleAffectedByEmpty() && (!style->emptyState() || element->hasChildNodes())))
1754        element->setNeedsStyleRecalc();
1755}
1756
1757static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
1758                                        Node* beforeChange, Node* afterChange, int childCountDelta)
1759{
1760    // :empty selector.
1761    checkForEmptyStyleChange(e, style);
1762
1763    if (!style || (e->needsStyleRecalc() && e->childrenAffectedByPositionalRules()))
1764        return;
1765
1766    // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1767    // In the DOM case, we only need to do something if |afterChange| is not 0.
1768    // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
1769    if (e->childrenAffectedByFirstChildRules() && afterChange) {
1770        // Find our new first child.
1771        Node* newFirstChild = 0;
1772        for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
1773
1774        // Find the first element node following |afterChange|
1775        Node* firstElementAfterInsertion = 0;
1776        for (firstElementAfterInsertion = afterChange;
1777             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1778             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1779
1780        // This is the insert/append case.
1781        if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
1782            firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
1783            firstElementAfterInsertion->setNeedsStyleRecalc();
1784
1785        // We also have to handle node removal.
1786        if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && (!newFirstChild->renderStyle() || !newFirstChild->renderStyle()->firstChildState()))
1787            newFirstChild->setNeedsStyleRecalc();
1788    }
1789
1790    // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1791    // In the DOM case, we only need to do something if |afterChange| is not 0.
1792    if (e->childrenAffectedByLastChildRules() && beforeChange) {
1793        // Find our new last child.
1794        Node* newLastChild = 0;
1795        for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
1796
1797        // Find the last element node going backwards from |beforeChange|
1798        Node* lastElementBeforeInsertion = 0;
1799        for (lastElementBeforeInsertion = beforeChange;
1800             lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
1801             lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
1802
1803        if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
1804            lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
1805            lastElementBeforeInsertion->setNeedsStyleRecalc();
1806
1807        // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
1808        // to match now.
1809        if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChild->renderStyle() || !newLastChild->renderStyle()->lastChildState()))
1810            newLastChild->setNeedsStyleRecalc();
1811    }
1812
1813    // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
1814    // that could be affected by this DOM change.
1815    if (e->childrenAffectedByDirectAdjacentRules() && afterChange) {
1816        Node* firstElementAfterInsertion = 0;
1817        for (firstElementAfterInsertion = afterChange;
1818             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
1819             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
1820        if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
1821            firstElementAfterInsertion->setNeedsStyleRecalc();
1822    }
1823
1824    // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
1825    // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
1826    // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
1827    // backward case.
1828    // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
1829    // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids
1830    // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
1831    if ((e->childrenAffectedByForwardPositionalRules() && afterChange)
1832        || (e->childrenAffectedByBackwardPositionalRules() && beforeChange))
1833        e->setNeedsStyleRecalc();
1834}
1835
1836void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
1837{
1838    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
1839    if (changedByParser)
1840        checkForEmptyStyleChange(this, renderStyle());
1841    else
1842        checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
1843
1844    if (ElementShadow * shadow = this->shadow())
1845        shadow->invalidateDistribution();
1846}
1847
1848void Element::removeAllEventListeners()
1849{
1850    ContainerNode::removeAllEventListeners();
1851    if (ElementShadow* shadow = this->shadow())
1852        shadow->removeAllEventListeners();
1853}
1854
1855void Element::beginParsingChildren()
1856{
1857    clearIsParsingChildrenFinished();
1858    StyleResolver* styleResolver = document()->styleResolverIfExists();
1859    if (styleResolver && attached())
1860        styleResolver->pushParentElement(this);
1861}
1862
1863void Element::finishParsingChildren()
1864{
1865    ContainerNode::finishParsingChildren();
1866    setIsParsingChildrenFinished();
1867    checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
1868    if (StyleResolver* styleResolver = document()->styleResolverIfExists())
1869        styleResolver->popParentElement(this);
1870}
1871
1872#ifndef NDEBUG
1873void Element::formatForDebugger(char* buffer, unsigned length) const
1874{
1875    StringBuilder result;
1876    String s;
1877
1878    result.append(nodeName());
1879
1880    s = getIdAttribute();
1881    if (s.length() > 0) {
1882        if (result.length() > 0)
1883            result.appendLiteral("; ");
1884        result.appendLiteral("id=");
1885        result.append(s);
1886    }
1887
1888    s = getAttribute(classAttr);
1889    if (s.length() > 0) {
1890        if (result.length() > 0)
1891            result.appendLiteral("; ");
1892        result.appendLiteral("class=");
1893        result.append(s);
1894    }
1895
1896    strncpy(buffer, result.toString().utf8().data(), length - 1);
1897}
1898#endif
1899
1900const Vector<RefPtr<Attr> >& Element::attrNodeList()
1901{
1902    ASSERT(hasSyntheticAttrChildNodes());
1903    return *attrNodeListForElement(this);
1904}
1905
1906PassRefPtr<Attr> Element::setAttributeNode(Attr* attrNode, ExceptionCode& ec)
1907{
1908    if (!attrNode) {
1909        ec = TYPE_MISMATCH_ERR;
1910        return 0;
1911    }
1912
1913    RefPtr<Attr> oldAttrNode = attrIfExists(attrNode->qualifiedName());
1914    if (oldAttrNode.get() == attrNode)
1915        return attrNode; // This Attr is already attached to the element.
1916
1917    // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object.
1918    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
1919    if (attrNode->ownerElement()) {
1920        ec = INUSE_ATTRIBUTE_ERR;
1921        return 0;
1922    }
1923
1924    synchronizeAllAttributes();
1925    UniqueElementData* elementData = ensureUniqueElementData();
1926
1927    unsigned index = elementData->getAttributeItemIndexForAttributeNode(attrNode);
1928    if (index != ElementData::attributeNotFound) {
1929        if (oldAttrNode)
1930            detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData->attributeItem(index)->value());
1931        else
1932            oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), elementData->attributeItem(index)->value());
1933    }
1934
1935    setAttributeInternal(index, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute);
1936
1937    attrNode->attachToElement(this);
1938    treeScope()->adoptIfNeeded(attrNode);
1939    ensureAttrNodeListForElement(this)->append(attrNode);
1940
1941    return oldAttrNode.release();
1942}
1943
1944PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
1945{
1946    return setAttributeNode(attr, ec);
1947}
1948
1949PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
1950{
1951    if (!attr) {
1952        ec = TYPE_MISMATCH_ERR;
1953        return 0;
1954    }
1955    if (attr->ownerElement() != this) {
1956        ec = NOT_FOUND_ERR;
1957        return 0;
1958    }
1959
1960    ASSERT(document() == attr->document());
1961
1962    synchronizeAttribute(attr->qualifiedName());
1963
1964    unsigned index = elementData()->getAttributeItemIndexForAttributeNode(attr);
1965    if (index == ElementData::attributeNotFound) {
1966        ec = NOT_FOUND_ERR;
1967        return 0;
1968    }
1969
1970    RefPtr<Attr> attrNode = attr;
1971    detachAttrNodeFromElementWithValue(attr, elementData()->attributeItem(index)->value());
1972    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
1973    return attrNode.release();
1974}
1975
1976bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode& ec)
1977{
1978    String prefix, localName;
1979    if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
1980        return false;
1981    ASSERT(!ec);
1982
1983    QualifiedName qName(prefix, localName, namespaceURI);
1984
1985    if (!Document::hasValidNamespaceForAttributes(qName)) {
1986        ec = NAMESPACE_ERR;
1987        return false;
1988    }
1989
1990    out = qName;
1991    return true;
1992}
1993
1994void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec)
1995{
1996    QualifiedName parsedName = anyName;
1997    if (!parseAttributeName(parsedName, namespaceURI, qualifiedName, ec))
1998        return;
1999    setAttribute(parsedName, value);
2000}
2001
2002void Element::removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
2003{
2004    ASSERT_WITH_SECURITY_IMPLICATION(index < attributeCount());
2005
2006    UniqueElementData* elementData = ensureUniqueElementData();
2007
2008    QualifiedName name = elementData->attributeItem(index)->name();
2009    AtomicString valueBeingRemoved = elementData->attributeItem(index)->value();
2010
2011    if (!inSynchronizationOfLazyAttribute) {
2012        if (!valueBeingRemoved.isNull())
2013            willModifyAttribute(name, valueBeingRemoved, nullAtom);
2014    }
2015
2016    if (RefPtr<Attr> attrNode = attrIfExists(name))
2017        detachAttrNodeFromElementWithValue(attrNode.get(), elementData->attributeItem(index)->value());
2018
2019    elementData->removeAttribute(index);
2020
2021    if (!inSynchronizationOfLazyAttribute)
2022        didRemoveAttribute(name);
2023}
2024
2025void Element::addAttributeInternal(const QualifiedName& name, const AtomicString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
2026{
2027    if (!inSynchronizationOfLazyAttribute)
2028        willModifyAttribute(name, nullAtom, value);
2029    ensureUniqueElementData()->addAttribute(name, value);
2030    if (!inSynchronizationOfLazyAttribute)
2031        didAddAttribute(name, value);
2032}
2033
2034void Element::removeAttribute(const AtomicString& name)
2035{
2036    if (!elementData())
2037        return;
2038
2039    AtomicString localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
2040    unsigned index = elementData()->getAttributeItemIndex(localName, false);
2041    if (index == ElementData::attributeNotFound) {
2042        if (UNLIKELY(localName == styleAttr) && elementData()->m_styleAttributeIsDirty && isStyledElement())
2043            static_cast<StyledElement*>(this)->removeAllInlineStyleProperties();
2044        return;
2045    }
2046
2047    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
2048}
2049
2050void Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName)
2051{
2052    removeAttribute(QualifiedName(nullAtom, localName, namespaceURI));
2053}
2054
2055PassRefPtr<Attr> Element::getAttributeNode(const AtomicString& localName)
2056{
2057    if (!elementData())
2058        return 0;
2059    synchronizeAttribute(localName);
2060    const Attribute* attribute = elementData()->getAttributeItem(localName, shouldIgnoreAttributeCase(this));
2061    if (!attribute)
2062        return 0;
2063    return ensureAttr(attribute->name());
2064}
2065
2066PassRefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
2067{
2068    if (!elementData())
2069        return 0;
2070    QualifiedName qName(nullAtom, localName, namespaceURI);
2071    synchronizeAttribute(qName);
2072    const Attribute* attribute = elementData()->getAttributeItem(qName);
2073    if (!attribute)
2074        return 0;
2075    return ensureAttr(attribute->name());
2076}
2077
2078bool Element::hasAttribute(const AtomicString& localName) const
2079{
2080    if (!elementData())
2081        return false;
2082    synchronizeAttribute(localName);
2083    return elementData()->getAttributeItem(shouldIgnoreAttributeCase(this) ? localName.lower() : localName, false);
2084}
2085
2086bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
2087{
2088    if (!elementData())
2089        return false;
2090    QualifiedName qName(nullAtom, localName, namespaceURI);
2091    synchronizeAttribute(qName);
2092    return elementData()->getAttributeItem(qName);
2093}
2094
2095CSSStyleDeclaration *Element::style()
2096{
2097    return 0;
2098}
2099
2100void Element::focus(bool restorePreviousSelection, FocusDirection direction)
2101{
2102    if (!inDocument())
2103        return;
2104
2105    Document* doc = document();
2106    if (doc->focusedElement() == this)
2107        return;
2108
2109    // If the stylesheets have already been loaded we can reliably check isFocusable.
2110    // If not, we continue and set the focused node on the focus controller below so
2111    // that it can be updated soon after attach.
2112    if (doc->haveStylesheetsLoaded()) {
2113        doc->updateLayoutIgnorePendingStylesheets();
2114        if (!isFocusable())
2115            return;
2116    }
2117
2118    if (!supportsFocus())
2119        return;
2120
2121    RefPtr<Node> protect;
2122    if (Page* page = doc->page()) {
2123        // Focus and change event handlers can cause us to lose our last ref.
2124        // If a focus event handler changes the focus to a different node it
2125        // does not make sense to continue and update appearence.
2126        protect = this;
2127        if (!page->focusController()->setFocusedElement(this, doc->frame(), direction))
2128            return;
2129    }
2130
2131    // Setting the focused node above might have invalidated the layout due to scripts.
2132    doc->updateLayoutIgnorePendingStylesheets();
2133
2134    if (!isFocusable()) {
2135        ensureElementRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
2136        return;
2137    }
2138
2139    cancelFocusAppearanceUpdate();
2140    updateFocusAppearance(restorePreviousSelection);
2141}
2142
2143void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
2144{
2145    if (isRootEditableElement()) {
2146        Frame* frame = document()->frame();
2147        if (!frame)
2148            return;
2149
2150        // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
2151        if (this == frame->selection()->rootEditableElement())
2152            return;
2153
2154        // FIXME: We should restore the previous selection if there is one.
2155        VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
2156
2157        if (frame->selection()->shouldChangeSelection(newSelection)) {
2158            frame->selection()->setSelection(newSelection);
2159            frame->selection()->revealSelection();
2160        }
2161    } else if (renderer() && !renderer()->isWidget())
2162        renderer()->scrollRectToVisible(boundingBox());
2163}
2164
2165void Element::blur()
2166{
2167    cancelFocusAppearanceUpdate();
2168    Document* doc = document();
2169    if (treeScope()->focusedElement() == this) {
2170        if (doc->frame())
2171            doc->frame()->page()->focusController()->setFocusedElement(0, doc->frame());
2172        else
2173            doc->setFocusedElement(0);
2174    }
2175}
2176
2177void Element::dispatchFocusInEvent(const AtomicString& eventType, PassRefPtr<Element> oldFocusedElement)
2178{
2179    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
2180    ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().DOMFocusInEvent);
2181    dispatchScopedEventDispatchMediator(FocusInEventDispatchMediator::create(FocusEvent::create(eventType, true, false, document()->defaultView(), 0, oldFocusedElement)));
2182}
2183
2184void Element::dispatchFocusOutEvent(const AtomicString& eventType, PassRefPtr<Element> newFocusedElement)
2185{
2186    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
2187    ASSERT(eventType == eventNames().focusoutEvent || eventType == eventNames().DOMFocusOutEvent);
2188    dispatchScopedEventDispatchMediator(FocusOutEventDispatchMediator::create(FocusEvent::create(eventType, true, false, document()->defaultView(), 0, newFocusedElement)));
2189}
2190
2191void Element::dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection)
2192{
2193    if (document()->page())
2194        document()->page()->chrome().client()->elementDidFocus(this);
2195
2196    RefPtr<FocusEvent> event = FocusEvent::create(eventNames().focusEvent, false, false, document()->defaultView(), 0, oldFocusedElement);
2197    EventDispatcher::dispatchEvent(this, FocusEventDispatchMediator::create(event.release()));
2198}
2199
2200void Element::dispatchBlurEvent(PassRefPtr<Element> newFocusedElement)
2201{
2202    if (document()->page())
2203        document()->page()->chrome().client()->elementDidBlur(this);
2204
2205    RefPtr<FocusEvent> event = FocusEvent::create(eventNames().blurEvent, false, false, document()->defaultView(), 0, newFocusedElement);
2206    EventDispatcher::dispatchEvent(this, BlurEventDispatchMediator::create(event.release()));
2207}
2208
2209
2210String Element::innerText()
2211{
2212    // We need to update layout, since plainText uses line boxes in the render tree.
2213    document()->updateLayoutIgnorePendingStylesheets();
2214
2215    if (!renderer())
2216        return textContent(true);
2217
2218    return plainText(rangeOfContents(const_cast<Element*>(this)).get());
2219}
2220
2221String Element::outerText()
2222{
2223    // Getting outerText is the same as getting innerText, only
2224    // setting is different. You would think this should get the plain
2225    // text for the outer range, but this is wrong, <br> for instance
2226    // would return different values for inner and outer text by such
2227    // a rule, but it doesn't in WinIE, and we want to match that.
2228    return innerText();
2229}
2230
2231String Element::title() const
2232{
2233    return String();
2234}
2235
2236const AtomicString& Element::pseudo() const
2237{
2238    return getAttribute(pseudoAttr);
2239}
2240
2241void Element::setPseudo(const AtomicString& value)
2242{
2243    setAttribute(pseudoAttr, value);
2244}
2245
2246LayoutSize Element::minimumSizeForResizing() const
2247{
2248    return hasRareData() ? elementRareData()->minimumSizeForResizing() : defaultMinimumSizeForResizing();
2249}
2250
2251void Element::setMinimumSizeForResizing(const LayoutSize& size)
2252{
2253    if (!hasRareData() && size == defaultMinimumSizeForResizing())
2254        return;
2255    ensureElementRareData()->setMinimumSizeForResizing(size);
2256}
2257
2258RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
2259{
2260    if (PseudoElement* element = pseudoElement(pseudoElementSpecifier))
2261        return element->computedStyle();
2262
2263    // FIXME: Find and use the renderer from the pseudo element instead of the actual element so that the 'length'
2264    // properties, which are only known by the renderer because it did the layout, will be correct and so that the
2265    // values returned for the ":selection" pseudo-element will be correct.
2266    if (RenderStyle* usedStyle = renderStyle()) {
2267        if (pseudoElementSpecifier) {
2268            RenderStyle* cachedPseudoStyle = usedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
2269            return cachedPseudoStyle ? cachedPseudoStyle : usedStyle;
2270         } else
2271            return usedStyle;
2272    }
2273
2274    if (!attached())
2275        // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
2276        // document tree and figure out when to destroy the computed style for such elements.
2277        return 0;
2278
2279    ElementRareData* data = ensureElementRareData();
2280    if (!data->computedStyle())
2281        data->setComputedStyle(document()->styleForElementIgnoringPendingStylesheets(this));
2282    return pseudoElementSpecifier ? data->computedStyle()->getCachedPseudoStyle(pseudoElementSpecifier) : data->computedStyle();
2283}
2284
2285void Element::setStyleAffectedByEmpty()
2286{
2287    ensureElementRareData()->setStyleAffectedByEmpty(true);
2288}
2289
2290void Element::setChildrenAffectedByHover(bool value)
2291{
2292    if (value || hasRareData())
2293        ensureElementRareData()->setChildrenAffectedByHover(value);
2294}
2295
2296void Element::setChildrenAffectedByActive(bool value)
2297{
2298    if (value || hasRareData())
2299        ensureElementRareData()->setChildrenAffectedByActive(value);
2300}
2301
2302void Element::setChildrenAffectedByDrag(bool value)
2303{
2304    if (value || hasRareData())
2305        ensureElementRareData()->setChildrenAffectedByDrag(value);
2306}
2307
2308void Element::setChildrenAffectedByFirstChildRules()
2309{
2310    ensureElementRareData()->setChildrenAffectedByFirstChildRules(true);
2311}
2312
2313void Element::setChildrenAffectedByLastChildRules()
2314{
2315    ensureElementRareData()->setChildrenAffectedByLastChildRules(true);
2316}
2317
2318void Element::setChildrenAffectedByDirectAdjacentRules()
2319{
2320    ensureElementRareData()->setChildrenAffectedByDirectAdjacentRules(true);
2321}
2322
2323void Element::setChildrenAffectedByForwardPositionalRules()
2324{
2325    ensureElementRareData()->setChildrenAffectedByForwardPositionalRules(true);
2326}
2327
2328void Element::setChildrenAffectedByBackwardPositionalRules()
2329{
2330    ensureElementRareData()->setChildrenAffectedByBackwardPositionalRules(true);
2331}
2332
2333void Element::setChildIndex(unsigned index)
2334{
2335    ElementRareData* rareData = ensureElementRareData();
2336    if (RenderStyle* style = renderStyle())
2337        style->setUnique();
2338    rareData->setChildIndex(index);
2339}
2340
2341bool Element::hasFlagsSetDuringStylingOfChildren() const
2342{
2343    if (!hasRareData())
2344        return false;
2345    return rareDataChildrenAffectedByHover()
2346        || rareDataChildrenAffectedByActive()
2347        || rareDataChildrenAffectedByDrag()
2348        || rareDataChildrenAffectedByFirstChildRules()
2349        || rareDataChildrenAffectedByLastChildRules()
2350        || rareDataChildrenAffectedByDirectAdjacentRules()
2351        || rareDataChildrenAffectedByForwardPositionalRules()
2352        || rareDataChildrenAffectedByBackwardPositionalRules();
2353}
2354
2355bool Element::rareDataStyleAffectedByEmpty() const
2356{
2357    ASSERT(hasRareData());
2358    return elementRareData()->styleAffectedByEmpty();
2359}
2360
2361bool Element::rareDataChildrenAffectedByHover() const
2362{
2363    ASSERT(hasRareData());
2364    return elementRareData()->childrenAffectedByHover();
2365}
2366
2367bool Element::rareDataChildrenAffectedByActive() const
2368{
2369    ASSERT(hasRareData());
2370    return elementRareData()->childrenAffectedByActive();
2371}
2372
2373bool Element::rareDataChildrenAffectedByDrag() const
2374{
2375    ASSERT(hasRareData());
2376    return elementRareData()->childrenAffectedByDrag();
2377}
2378
2379bool Element::rareDataChildrenAffectedByFirstChildRules() const
2380{
2381    ASSERT(hasRareData());
2382    return elementRareData()->childrenAffectedByFirstChildRules();
2383}
2384
2385bool Element::rareDataChildrenAffectedByLastChildRules() const
2386{
2387    ASSERT(hasRareData());
2388    return elementRareData()->childrenAffectedByLastChildRules();
2389}
2390
2391bool Element::rareDataChildrenAffectedByDirectAdjacentRules() const
2392{
2393    ASSERT(hasRareData());
2394    return elementRareData()->childrenAffectedByDirectAdjacentRules();
2395}
2396
2397bool Element::rareDataChildrenAffectedByForwardPositionalRules() const
2398{
2399    ASSERT(hasRareData());
2400    return elementRareData()->childrenAffectedByForwardPositionalRules();
2401}
2402
2403bool Element::rareDataChildrenAffectedByBackwardPositionalRules() const
2404{
2405    ASSERT(hasRareData());
2406    return elementRareData()->childrenAffectedByBackwardPositionalRules();
2407}
2408
2409unsigned Element::rareDataChildIndex() const
2410{
2411    ASSERT(hasRareData());
2412    return elementRareData()->childIndex();
2413}
2414
2415void Element::setIsInCanvasSubtree(bool isInCanvasSubtree)
2416{
2417    ensureElementRareData()->setIsInCanvasSubtree(isInCanvasSubtree);
2418}
2419
2420bool Element::isInCanvasSubtree() const
2421{
2422    return hasRareData() && elementRareData()->isInCanvasSubtree();
2423}
2424
2425void Element::setIsInsideRegion(bool value)
2426{
2427    if (value == isInsideRegion())
2428        return;
2429
2430    ensureElementRareData()->setIsInsideRegion(value);
2431}
2432
2433bool Element::isInsideRegion() const
2434{
2435    return hasRareData() ? elementRareData()->isInsideRegion() : false;
2436}
2437
2438AtomicString Element::computeInheritedLanguage() const
2439{
2440    const Node* n = this;
2441    AtomicString value;
2442    // The language property is inherited, so we iterate over the parents to find the first language.
2443    do {
2444        if (n->isElementNode()) {
2445            if (const ElementData* elementData = toElement(n)->elementData()) {
2446                // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
2447                if (const Attribute* attribute = elementData->getAttributeItem(XMLNames::langAttr))
2448                    value = attribute->value();
2449                else if (const Attribute* attribute = elementData->getAttributeItem(HTMLNames::langAttr))
2450                    value = attribute->value();
2451            }
2452        } else if (n->isDocumentNode()) {
2453            // checking the MIME content-language
2454            value = toDocument(n)->contentLanguage();
2455        }
2456
2457        n = n->parentNode();
2458    } while (n && value.isNull());
2459
2460    return value;
2461}
2462
2463Locale& Element::locale() const
2464{
2465    return document()->getCachedLocale(computeInheritedLanguage());
2466}
2467
2468void Element::cancelFocusAppearanceUpdate()
2469{
2470    if (hasRareData())
2471        elementRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
2472    if (document()->focusedElement() == this)
2473        document()->cancelFocusAppearanceUpdate();
2474}
2475
2476void Element::normalizeAttributes()
2477{
2478    if (!hasAttributes())
2479        return;
2480    for (unsigned i = 0; i < attributeCount(); ++i) {
2481        if (RefPtr<Attr> attr = attrIfExists(attributeItem(i)->name()))
2482            attr->normalize();
2483    }
2484}
2485
2486void Element::updatePseudoElement(PseudoId pseudoId, StyleChange change)
2487{
2488    PseudoElement* existing = pseudoElement(pseudoId);
2489    if (existing) {
2490        // PseudoElement styles hang off their parent element's style so if we needed
2491        // a style recalc we should Force one on the pseudo.
2492        existing->recalcStyle(needsStyleRecalc() ? Force : change);
2493
2494        // Wait until our parent is not displayed or pseudoElementRendererIsNeeded
2495        // is false, otherwise we could continously create and destroy PseudoElements
2496        // when RenderObject::isChildAllowed on our parent returns false for the
2497        // PseudoElement's renderer for each style recalc.
2498        if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedPseudoStyle(pseudoId)))
2499            setPseudoElement(pseudoId, 0);
2500    } else if (RefPtr<PseudoElement> element = createPseudoElementIfNeeded(pseudoId)) {
2501        element->attach();
2502        setPseudoElement(pseudoId, element.release());
2503    }
2504}
2505
2506PassRefPtr<PseudoElement> Element::createPseudoElementIfNeeded(PseudoId pseudoId)
2507{
2508    if (!document()->styleSheetCollection()->usesBeforeAfterRules())
2509        return 0;
2510
2511    if (!renderer() || !renderer()->canHaveGeneratedChildren())
2512        return 0;
2513
2514    if (isPseudoElement())
2515        return 0;
2516
2517    if (!pseudoElementRendererIsNeeded(renderer()->getCachedPseudoStyle(pseudoId)))
2518        return 0;
2519
2520    return PseudoElement::create(this, pseudoId);
2521}
2522
2523bool Element::hasPseudoElements() const
2524{
2525    return hasRareData() && elementRareData()->hasPseudoElements();
2526}
2527
2528PseudoElement* Element::pseudoElement(PseudoId pseudoId) const
2529{
2530    return hasRareData() ? elementRareData()->pseudoElement(pseudoId) : 0;
2531}
2532
2533void Element::setPseudoElement(PseudoId pseudoId, PassRefPtr<PseudoElement> element)
2534{
2535    ensureElementRareData()->setPseudoElement(pseudoId, element);
2536    resetNeedsShadowTreeWalker();
2537}
2538
2539RenderObject* Element::pseudoElementRenderer(PseudoId pseudoId) const
2540{
2541    if (PseudoElement* element = pseudoElement(pseudoId))
2542        return element->renderer();
2543    return 0;
2544}
2545
2546// ElementTraversal API
2547Element* Element::firstElementChild() const
2548{
2549    return ElementTraversal::firstWithin(this);
2550}
2551
2552Element* Element::lastElementChild() const
2553{
2554    Node* n = lastChild();
2555    while (n && !n->isElementNode())
2556        n = n->previousSibling();
2557    return toElement(n);
2558}
2559
2560unsigned Element::childElementCount() const
2561{
2562    unsigned count = 0;
2563    Node* n = firstChild();
2564    while (n) {
2565        count += n->isElementNode();
2566        n = n->nextSibling();
2567    }
2568    return count;
2569}
2570
2571bool Element::matchesReadOnlyPseudoClass() const
2572{
2573    return false;
2574}
2575
2576bool Element::matchesReadWritePseudoClass() const
2577{
2578    return false;
2579}
2580
2581bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
2582{
2583    if (selector.isEmpty()) {
2584        ec = SYNTAX_ERR;
2585        return false;
2586    }
2587
2588    SelectorQuery* selectorQuery = document()->selectorQueryCache()->add(selector, document(), ec);
2589    if (!selectorQuery)
2590        return false;
2591    return selectorQuery->matches(this);
2592}
2593
2594bool Element::shouldAppearIndeterminate() const
2595{
2596    return false;
2597}
2598
2599DOMTokenList* Element::classList()
2600{
2601    ElementRareData* data = ensureElementRareData();
2602    if (!data->classList())
2603        data->setClassList(ClassList::create(this));
2604    return data->classList();
2605}
2606
2607DOMStringMap* Element::dataset()
2608{
2609    ElementRareData* data = ensureElementRareData();
2610    if (!data->dataset())
2611        data->setDataset(DatasetDOMStringMap::create(this));
2612    return data->dataset();
2613}
2614
2615KURL Element::getURLAttribute(const QualifiedName& name) const
2616{
2617#if !ASSERT_DISABLED
2618    if (elementData()) {
2619        if (const Attribute* attribute = getAttributeItem(name))
2620            ASSERT(isURLAttribute(*attribute));
2621    }
2622#endif
2623    return document()->completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
2624}
2625
2626KURL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
2627{
2628#if !ASSERT_DISABLED
2629    if (elementData()) {
2630        if (const Attribute* attribute = getAttributeItem(name))
2631            ASSERT(isURLAttribute(*attribute));
2632    }
2633#endif
2634    String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
2635    if (value.isEmpty())
2636        return KURL();
2637    return document()->completeURL(value);
2638}
2639
2640int Element::getIntegralAttribute(const QualifiedName& attributeName) const
2641{
2642    return getAttribute(attributeName).string().toInt();
2643}
2644
2645void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
2646{
2647    // FIXME: Need an AtomicString version of String::number.
2648    setAttribute(attributeName, String::number(value));
2649}
2650
2651unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
2652{
2653    return getAttribute(attributeName).string().toUInt();
2654}
2655
2656void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
2657{
2658    // FIXME: Need an AtomicString version of String::number.
2659    setAttribute(attributeName, String::number(value));
2660}
2661
2662#if ENABLE(SVG)
2663bool Element::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
2664{
2665    // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
2666    if (childContext.node()->isSVGElement())
2667        return childContext.node()->hasTagName(SVGNames::svgTag) || isSVGElement();
2668
2669    return ContainerNode::childShouldCreateRenderer(childContext);
2670}
2671#endif
2672
2673#if ENABLE(FULLSCREEN_API)
2674void Element::webkitRequestFullscreen()
2675{
2676    document()->requestFullScreenForElement(this, ALLOW_KEYBOARD_INPUT, Document::EnforceIFrameAllowFullScreenRequirement);
2677}
2678
2679void Element::webkitRequestFullScreen(unsigned short flags)
2680{
2681    document()->requestFullScreenForElement(this, (flags | LEGACY_MOZILLA_REQUEST), Document::EnforceIFrameAllowFullScreenRequirement);
2682}
2683
2684bool Element::containsFullScreenElement() const
2685{
2686    return hasRareData() && elementRareData()->containsFullScreenElement();
2687}
2688
2689void Element::setContainsFullScreenElement(bool flag)
2690{
2691    ensureElementRareData()->setContainsFullScreenElement(flag);
2692    setNeedsStyleRecalc(SyntheticStyleChange);
2693}
2694
2695static Element* parentCrossingFrameBoundaries(Element* element)
2696{
2697    ASSERT(element);
2698    return element->parentElement() ? element->parentElement() : element->document()->ownerElement();
2699}
2700
2701void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
2702{
2703    Element* element = this;
2704    while ((element = parentCrossingFrameBoundaries(element)))
2705        element->setContainsFullScreenElement(flag);
2706}
2707#endif
2708
2709#if ENABLE(DIALOG_ELEMENT)
2710bool Element::isInTopLayer() const
2711{
2712    return hasRareData() && elementRareData()->isInTopLayer();
2713}
2714
2715void Element::setIsInTopLayer(bool inTopLayer)
2716{
2717    if (isInTopLayer() == inTopLayer)
2718        return;
2719    ensureElementRareData()->setIsInTopLayer(inTopLayer);
2720
2721    // We must ensure a reattach occurs so the renderer is inserted in the correct sibling order under RenderView according to its
2722    // top layer position, or in its usual place if not in the top layer.
2723    reattachIfAttached();
2724}
2725#endif
2726
2727#if ENABLE(POINTER_LOCK)
2728void Element::webkitRequestPointerLock()
2729{
2730    if (document()->page())
2731        document()->page()->pointerLockController()->requestPointerLock(this);
2732}
2733#endif
2734
2735SpellcheckAttributeState Element::spellcheckAttributeState() const
2736{
2737    const AtomicString& value = getAttribute(HTMLNames::spellcheckAttr);
2738    if (value == nullAtom)
2739        return SpellcheckAttributeDefault;
2740    if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, ""))
2741        return SpellcheckAttributeTrue;
2742    if (equalIgnoringCase(value, "false"))
2743        return SpellcheckAttributeFalse;
2744
2745    return SpellcheckAttributeDefault;
2746}
2747
2748bool Element::isSpellCheckingEnabled() const
2749{
2750    for (const Element* element = this; element; element = element->parentOrShadowHostElement()) {
2751        switch (element->spellcheckAttributeState()) {
2752        case SpellcheckAttributeTrue:
2753            return true;
2754        case SpellcheckAttributeFalse:
2755            return false;
2756        case SpellcheckAttributeDefault:
2757            break;
2758        }
2759    }
2760
2761    return true;
2762}
2763
2764RenderRegion* Element::renderRegion() const
2765{
2766    if (renderer() && renderer()->isRenderRegion())
2767        return toRenderRegion(renderer());
2768
2769    return 0;
2770}
2771
2772#if ENABLE(CSS_REGIONS)
2773
2774bool Element::shouldMoveToFlowThread(RenderStyle* styleToUse) const
2775{
2776    ASSERT(styleToUse);
2777
2778#if ENABLE(FULLSCREEN_API)
2779    if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == this)
2780        return false;
2781#endif
2782
2783    if (isInShadowTree())
2784        return false;
2785
2786    if (styleToUse->flowThread().isEmpty())
2787        return false;
2788
2789    return !isRegisteredWithNamedFlow();
2790}
2791
2792const AtomicString& Element::webkitRegionOverset() const
2793{
2794    document()->updateLayoutIgnorePendingStylesheets();
2795
2796    DEFINE_STATIC_LOCAL(AtomicString, undefinedState, ("undefined", AtomicString::ConstructFromLiteral));
2797    if (!document()->cssRegionsEnabled() || !renderRegion())
2798        return undefinedState;
2799
2800    switch (renderRegion()->regionState()) {
2801    case RenderRegion::RegionFit: {
2802        DEFINE_STATIC_LOCAL(AtomicString, fitState, ("fit", AtomicString::ConstructFromLiteral));
2803        return fitState;
2804    }
2805    case RenderRegion::RegionEmpty: {
2806        DEFINE_STATIC_LOCAL(AtomicString, emptyState, ("empty", AtomicString::ConstructFromLiteral));
2807        return emptyState;
2808    }
2809    case RenderRegion::RegionOverset: {
2810        DEFINE_STATIC_LOCAL(AtomicString, overflowState, ("overset", AtomicString::ConstructFromLiteral));
2811        return overflowState;
2812    }
2813    case RenderRegion::RegionUndefined:
2814        return undefinedState;
2815    }
2816
2817    ASSERT_NOT_REACHED();
2818    return undefinedState;
2819}
2820
2821Vector<RefPtr<Range> > Element::webkitGetRegionFlowRanges() const
2822{
2823    document()->updateLayoutIgnorePendingStylesheets();
2824
2825    Vector<RefPtr<Range> > rangeObjects;
2826    if (document()->cssRegionsEnabled() && renderer() && renderer()->isRenderRegion()) {
2827        RenderRegion* region = toRenderRegion(renderer());
2828        if (region->isValid())
2829            region->getRanges(rangeObjects);
2830    }
2831
2832    return rangeObjects;
2833}
2834
2835#endif
2836
2837#ifndef NDEBUG
2838bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
2839{
2840    if (name == HTMLNames::styleAttr)
2841        return false;
2842
2843#if ENABLE(SVG)
2844    if (isSVGElement())
2845        return !static_cast<const SVGElement*>(this)->isAnimatableAttribute(name);
2846#endif
2847
2848    return true;
2849}
2850#endif
2851
2852#ifdef DUMP_NODE_STATISTICS
2853bool Element::hasNamedNodeMap() const
2854{
2855    return hasRareData() && elementRareData()->attributeMap();
2856}
2857#endif
2858
2859inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
2860{
2861    if (!isInTreeScope())
2862        return;
2863
2864    if (oldName == newName)
2865        return;
2866
2867    updateNameForTreeScope(treeScope(), oldName, newName);
2868
2869    if (!inDocument())
2870        return;
2871    Document* htmlDocument = document();
2872    if (!htmlDocument->isHTMLDocument())
2873        return;
2874    updateNameForDocument(toHTMLDocument(htmlDocument), oldName, newName);
2875}
2876
2877void Element::updateNameForTreeScope(TreeScope* scope, const AtomicString& oldName, const AtomicString& newName)
2878{
2879    ASSERT(isInTreeScope());
2880    ASSERT(oldName != newName);
2881
2882    if (!oldName.isEmpty())
2883        scope->removeElementByName(oldName, this);
2884    if (!newName.isEmpty())
2885        scope->addElementByName(newName, this);
2886}
2887
2888void Element::updateNameForDocument(HTMLDocument* document, const AtomicString& oldName, const AtomicString& newName)
2889{
2890    ASSERT(inDocument());
2891    ASSERT(oldName != newName);
2892
2893    if (WindowNameCollection::nodeMatchesIfNameAttributeMatch(this)) {
2894        const AtomicString& id = WindowNameCollection::nodeMatchesIfIdAttributeMatch(this) ? getIdAttribute() : nullAtom;
2895        if (!oldName.isEmpty() && oldName != id)
2896            document->windowNamedItemMap().remove(oldName.impl(), this);
2897        if (!newName.isEmpty() && newName != id)
2898            document->windowNamedItemMap().add(newName.impl(), this, treeScope());
2899    }
2900
2901    if (DocumentNameCollection::nodeMatchesIfNameAttributeMatch(this)) {
2902        const AtomicString& id = DocumentNameCollection::nodeMatchesIfIdAttributeMatch(this) ? getIdAttribute() : nullAtom;
2903        if (!oldName.isEmpty() && oldName != id)
2904            document->documentNamedItemMap().remove(oldName.impl(), this);
2905        if (!newName.isEmpty() && newName != id)
2906            document->documentNamedItemMap().add(newName.impl(), this, treeScope());
2907    }
2908}
2909
2910inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
2911{
2912    if (!isInTreeScope())
2913        return;
2914
2915    if (oldId == newId)
2916        return;
2917
2918    updateIdForTreeScope(treeScope(), oldId, newId);
2919
2920    if (!inDocument())
2921        return;
2922    Document* htmlDocument = document();
2923    if (!htmlDocument->isHTMLDocument())
2924        return;
2925    updateIdForDocument(toHTMLDocument(htmlDocument), oldId, newId, UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute);
2926}
2927
2928void Element::updateIdForTreeScope(TreeScope* scope, const AtomicString& oldId, const AtomicString& newId)
2929{
2930    ASSERT(isInTreeScope());
2931    ASSERT(oldId != newId);
2932
2933    if (!oldId.isEmpty())
2934        scope->removeElementById(oldId, this);
2935    if (!newId.isEmpty())
2936        scope->addElementById(newId, this);
2937}
2938
2939void Element::updateIdForDocument(HTMLDocument* document, const AtomicString& oldId, const AtomicString& newId, HTMLDocumentNamedItemMapsUpdatingCondition condition)
2940{
2941    ASSERT(inDocument());
2942    ASSERT(oldId != newId);
2943
2944    if (WindowNameCollection::nodeMatchesIfIdAttributeMatch(this)) {
2945        const AtomicString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && WindowNameCollection::nodeMatchesIfNameAttributeMatch(this) ? getNameAttribute() : nullAtom;
2946        if (!oldId.isEmpty() && oldId != name)
2947            document->windowNamedItemMap().remove(oldId.impl(), this);
2948        if (!newId.isEmpty() && newId != name)
2949            document->windowNamedItemMap().add(newId.impl(), this, treeScope());
2950    }
2951
2952    if (DocumentNameCollection::nodeMatchesIfIdAttributeMatch(this)) {
2953        const AtomicString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && DocumentNameCollection::nodeMatchesIfNameAttributeMatch(this) ? getNameAttribute() : nullAtom;
2954        if (!oldId.isEmpty() && oldId != name)
2955            document->documentNamedItemMap().remove(oldId.impl(), this);
2956        if (!newId.isEmpty() && newId != name)
2957            document->documentNamedItemMap().add(newId.impl(), this, treeScope());
2958    }
2959}
2960
2961void Element::updateLabel(TreeScope* scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
2962{
2963    ASSERT(hasTagName(labelTag));
2964
2965    if (!inDocument())
2966        return;
2967
2968    if (oldForAttributeValue == newForAttributeValue)
2969        return;
2970
2971    if (!oldForAttributeValue.isEmpty())
2972        scope->removeLabel(oldForAttributeValue, static_cast<HTMLLabelElement*>(this));
2973    if (!newForAttributeValue.isEmpty())
2974        scope->addLabel(newForAttributeValue, static_cast<HTMLLabelElement*>(this));
2975}
2976
2977void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
2978{
2979    if (isIdAttributeName(name))
2980        updateId(oldValue, newValue);
2981    else if (name == HTMLNames::nameAttr)
2982        updateName(oldValue, newValue);
2983    else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
2984        TreeScope* scope = treeScope();
2985        if (scope->shouldCacheLabelsByForAttribute())
2986            updateLabel(scope, oldValue, newValue);
2987    }
2988
2989    if (oldValue != newValue) {
2990        if (attached() && document()->styleResolverIfExists() && document()->styleResolverIfExists()->hasSelectorForAttribute(name.localName()))
2991            setNeedsStyleRecalc();
2992    }
2993
2994    if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
2995        recipients->enqueueMutationRecord(MutationRecord::createAttributes(this, name, oldValue));
2996
2997#if ENABLE(INSPECTOR)
2998    InspectorInstrumentation::willModifyDOMAttr(document(), this, oldValue, newValue);
2999#endif
3000}
3001
3002void Element::didAddAttribute(const QualifiedName& name, const AtomicString& value)
3003{
3004    attributeChanged(name, value);
3005    InspectorInstrumentation::didModifyDOMAttr(document(), this, name.localName(), value);
3006    dispatchSubtreeModifiedEvent();
3007}
3008
3009void Element::didModifyAttribute(const QualifiedName& name, const AtomicString& value)
3010{
3011    attributeChanged(name, value);
3012    InspectorInstrumentation::didModifyDOMAttr(document(), this, name.localName(), value);
3013    // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
3014}
3015
3016void Element::didRemoveAttribute(const QualifiedName& name)
3017{
3018    attributeChanged(name, nullAtom);
3019    InspectorInstrumentation::didRemoveDOMAttr(document(), this, name.localName());
3020    dispatchSubtreeModifiedEvent();
3021}
3022
3023PassRefPtr<HTMLCollection> Element::ensureCachedHTMLCollection(CollectionType type)
3024{
3025    if (HTMLCollection* collection = cachedHTMLCollection(type))
3026        return collection;
3027
3028    RefPtr<HTMLCollection> collection;
3029    if (type == TableRows) {
3030        ASSERT(hasTagName(tableTag));
3031        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLTableRowsCollection>(this, type);
3032    } else if (type == SelectOptions) {
3033        ASSERT(hasTagName(selectTag));
3034        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLOptionsCollection>(this, type);
3035    } else if (type == FormControls) {
3036        ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
3037        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLFormControlsCollection>(this, type);
3038#if ENABLE(MICRODATA)
3039    } else if (type == ItemProperties) {
3040        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLPropertiesCollection>(this, type);
3041#endif
3042    }
3043    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLCollection>(this, type);
3044}
3045
3046HTMLCollection* Element::cachedHTMLCollection(CollectionType type)
3047{
3048    return hasRareData() && rareData()->nodeLists() ? rareData()->nodeLists()->cacheWithAtomicName<HTMLCollection>(type) : 0;
3049}
3050
3051IntSize Element::savedLayerScrollOffset() const
3052{
3053    return hasRareData() ? elementRareData()->savedLayerScrollOffset() : IntSize();
3054}
3055
3056void Element::setSavedLayerScrollOffset(const IntSize& size)
3057{
3058    if (size.isZero() && !hasRareData())
3059        return;
3060    ensureElementRareData()->setSavedLayerScrollOffset(size);
3061}
3062
3063PassRefPtr<Attr> Element::attrIfExists(const QualifiedName& name)
3064{
3065    if (AttrNodeList* attrNodeList = attrNodeListForElement(this))
3066        return findAttrNodeInList(attrNodeList, name);
3067    return 0;
3068}
3069
3070PassRefPtr<Attr> Element::ensureAttr(const QualifiedName& name)
3071{
3072    AttrNodeList* attrNodeList = ensureAttrNodeListForElement(this);
3073    RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, name);
3074    if (!attrNode) {
3075        attrNode = Attr::create(this, name);
3076        treeScope()->adoptIfNeeded(attrNode.get());
3077        attrNodeList->append(attrNode);
3078    }
3079    return attrNode.release();
3080}
3081
3082void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomicString& value)
3083{
3084    ASSERT(hasSyntheticAttrChildNodes());
3085    attrNode->detachFromElementWithValue(value);
3086
3087    AttrNodeList* attrNodeList = attrNodeListForElement(this);
3088    for (unsigned i = 0; i < attrNodeList->size(); ++i) {
3089        if (attrNodeList->at(i)->qualifiedName() == attrNode->qualifiedName()) {
3090            attrNodeList->remove(i);
3091            if (attrNodeList->isEmpty())
3092                removeAttrNodeListForElement(this);
3093            return;
3094        }
3095    }
3096    ASSERT_NOT_REACHED();
3097}
3098
3099void Element::detachAllAttrNodesFromElement()
3100{
3101    AttrNodeList* attrNodeList = attrNodeListForElement(this);
3102    ASSERT(attrNodeList);
3103
3104    for (unsigned i = 0; i < attributeCount(); ++i) {
3105        const Attribute* attribute = attributeItem(i);
3106        if (RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, attribute->name()))
3107            attrNode->detachFromElementWithValue(attribute->value());
3108    }
3109
3110    removeAttrNodeListForElement(this);
3111}
3112
3113bool Element::willRecalcStyle(StyleChange)
3114{
3115    ASSERT(hasCustomStyleCallbacks());
3116    return true;
3117}
3118
3119void Element::didRecalcStyle(StyleChange)
3120{
3121    ASSERT(hasCustomStyleCallbacks());
3122}
3123
3124
3125PassRefPtr<RenderStyle> Element::customStyleForRenderer()
3126{
3127    ASSERT(hasCustomStyleCallbacks());
3128    return 0;
3129}
3130
3131void Element::cloneAttributesFromElement(const Element& other)
3132{
3133    if (hasSyntheticAttrChildNodes())
3134        detachAllAttrNodesFromElement();
3135
3136    other.synchronizeAllAttributes();
3137    if (!other.m_elementData) {
3138        m_elementData.clear();
3139        return;
3140    }
3141
3142    // We can't update window and document's named item maps since the presence of image and object elements depend on other attributes and children.
3143    // Fortunately, those named item maps are only updated when this element is in the document, which should never be the case.
3144    ASSERT(!inDocument());
3145
3146    const AtomicString& oldID = getIdAttribute();
3147    const AtomicString& newID = other.getIdAttribute();
3148
3149    if (!oldID.isNull() || !newID.isNull())
3150        updateId(oldID, newID);
3151
3152    const AtomicString& oldName = getNameAttribute();
3153    const AtomicString& newName = other.getNameAttribute();
3154
3155    if (!oldName.isNull() || !newName.isNull())
3156        updateName(oldName, newName);
3157
3158    // If 'other' has a mutable ElementData, convert it to an immutable one so we can share it between both elements.
3159    // We can only do this if there is no CSSOM wrapper for other's inline style, and there are no presentation attributes.
3160    if (other.m_elementData->isUnique()
3161        && !other.m_elementData->presentationAttributeStyle()
3162        && (!other.m_elementData->inlineStyle() || !other.m_elementData->inlineStyle()->hasCSSOMWrapper()))
3163        const_cast<Element&>(other).m_elementData = static_cast<const UniqueElementData*>(other.m_elementData.get())->makeShareableCopy();
3164
3165    if (!other.m_elementData->isUnique())
3166        m_elementData = other.m_elementData;
3167    else
3168        m_elementData = other.m_elementData->makeUniqueCopy();
3169
3170    for (unsigned i = 0; i < m_elementData->length(); ++i) {
3171        const Attribute* attribute = const_cast<const ElementData*>(m_elementData.get())->attributeItem(i);
3172        attributeChangedFromParserOrByCloning(attribute->name(), attribute->value(), ModifiedByCloning);
3173    }
3174}
3175
3176void Element::cloneDataFromElement(const Element& other)
3177{
3178    cloneAttributesFromElement(other);
3179    copyNonAttributePropertiesFromElement(other);
3180}
3181
3182void Element::createUniqueElementData()
3183{
3184    if (!m_elementData)
3185        m_elementData = UniqueElementData::create();
3186    else {
3187        ASSERT(!m_elementData->isUnique());
3188        m_elementData = static_cast<ShareableElementData*>(m_elementData.get())->makeUniqueCopy();
3189    }
3190}
3191
3192#if ENABLE(SVG)
3193bool Element::hasPendingResources() const
3194{
3195    return hasRareData() && elementRareData()->hasPendingResources();
3196}
3197
3198void Element::setHasPendingResources()
3199{
3200    ensureElementRareData()->setHasPendingResources(true);
3201}
3202
3203void Element::clearHasPendingResources()
3204{
3205    ensureElementRareData()->setHasPendingResources(false);
3206}
3207#endif
3208
3209void ElementData::deref()
3210{
3211    if (!derefBase())
3212        return;
3213
3214    if (m_isUnique)
3215        delete static_cast<UniqueElementData*>(this);
3216    else
3217        delete static_cast<ShareableElementData*>(this);
3218}
3219
3220ElementData::ElementData()
3221    : m_isUnique(true)
3222    , m_arraySize(0)
3223    , m_hasNameAttribute(false)
3224    , m_presentationAttributeStyleIsDirty(false)
3225    , m_styleAttributeIsDirty(false)
3226#if ENABLE(SVG)
3227    , m_animatedSVGAttributesAreDirty(false)
3228#endif
3229{
3230}
3231
3232ElementData::ElementData(unsigned arraySize)
3233    : m_isUnique(false)
3234    , m_arraySize(arraySize)
3235    , m_hasNameAttribute(false)
3236    , m_presentationAttributeStyleIsDirty(false)
3237    , m_styleAttributeIsDirty(false)
3238#if ENABLE(SVG)
3239    , m_animatedSVGAttributesAreDirty(false)
3240#endif
3241{
3242}
3243
3244struct SameSizeAsElementData : public RefCounted<SameSizeAsElementData> {
3245    unsigned bitfield;
3246    void* refPtrs[3];
3247};
3248
3249COMPILE_ASSERT(sizeof(ElementData) == sizeof(SameSizeAsElementData), element_attribute_data_should_stay_small);
3250
3251static size_t sizeForShareableElementDataWithAttributeCount(unsigned count)
3252{
3253    return sizeof(ShareableElementData) + sizeof(Attribute) * count;
3254}
3255
3256PassRefPtr<ShareableElementData> ShareableElementData::createWithAttributes(const Vector<Attribute>& attributes)
3257{
3258    void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()));
3259    return adoptRef(new (NotNull, slot) ShareableElementData(attributes));
3260}
3261
3262PassRefPtr<UniqueElementData> UniqueElementData::create()
3263{
3264    return adoptRef(new UniqueElementData);
3265}
3266
3267ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes)
3268    : ElementData(attributes.size())
3269{
3270    for (unsigned i = 0; i < m_arraySize; ++i)
3271        new (NotNull, &m_attributeArray[i]) Attribute(attributes[i]);
3272}
3273
3274ShareableElementData::~ShareableElementData()
3275{
3276    for (unsigned i = 0; i < m_arraySize; ++i)
3277        m_attributeArray[i].~Attribute();
3278}
3279
3280ShareableElementData::ShareableElementData(const UniqueElementData& other)
3281    : ElementData(other, false)
3282{
3283    ASSERT(!other.m_presentationAttributeStyle);
3284
3285    if (other.m_inlineStyle) {
3286        ASSERT(!other.m_inlineStyle->hasCSSOMWrapper());
3287        m_inlineStyle = other.m_inlineStyle->immutableCopyIfNeeded();
3288    }
3289
3290    for (unsigned i = 0; i < m_arraySize; ++i)
3291        new (NotNull, &m_attributeArray[i]) Attribute(other.m_attributeVector.at(i));
3292}
3293
3294ElementData::ElementData(const ElementData& other, bool isUnique)
3295    : m_isUnique(isUnique)
3296    , m_arraySize(isUnique ? 0 : other.length())
3297    , m_hasNameAttribute(other.m_hasNameAttribute)
3298    , m_presentationAttributeStyleIsDirty(other.m_presentationAttributeStyleIsDirty)
3299    , m_styleAttributeIsDirty(other.m_styleAttributeIsDirty)
3300#if ENABLE(SVG)
3301    , m_animatedSVGAttributesAreDirty(other.m_animatedSVGAttributesAreDirty)
3302#endif
3303    , m_classNames(other.m_classNames)
3304    , m_idForStyleResolution(other.m_idForStyleResolution)
3305{
3306    // NOTE: The inline style is copied by the subclass copy constructor since we don't know what to do with it here.
3307}
3308
3309UniqueElementData::UniqueElementData()
3310{
3311}
3312
3313UniqueElementData::UniqueElementData(const UniqueElementData& other)
3314    : ElementData(other, true)
3315    , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
3316    , m_attributeVector(other.m_attributeVector)
3317{
3318    m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->mutableCopy() : 0;
3319}
3320
3321UniqueElementData::UniqueElementData(const ShareableElementData& other)
3322    : ElementData(other, true)
3323{
3324    // An ShareableElementData should never have a mutable inline StylePropertySet attached.
3325    ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable());
3326    m_inlineStyle = other.m_inlineStyle;
3327
3328    m_attributeVector.reserveCapacity(other.length());
3329    for (unsigned i = 0; i < other.length(); ++i)
3330        m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
3331}
3332
3333PassRefPtr<UniqueElementData> ElementData::makeUniqueCopy() const
3334{
3335    if (isUnique())
3336        return adoptRef(new UniqueElementData(static_cast<const UniqueElementData&>(*this)));
3337    return adoptRef(new UniqueElementData(static_cast<const ShareableElementData&>(*this)));
3338}
3339
3340PassRefPtr<ShareableElementData> UniqueElementData::makeShareableCopy() const
3341{
3342    void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
3343    return adoptRef(new (NotNull, slot) ShareableElementData(*this));
3344}
3345
3346void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomicString& value)
3347{
3348    m_attributeVector.append(Attribute(attributeName, value));
3349}
3350
3351void UniqueElementData::removeAttribute(unsigned index)
3352{
3353    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
3354    m_attributeVector.remove(index);
3355}
3356
3357bool ElementData::isEquivalent(const ElementData* other) const
3358{
3359    if (!other)
3360        return isEmpty();
3361
3362    unsigned len = length();
3363    if (len != other->length())
3364        return false;
3365
3366    for (unsigned i = 0; i < len; i++) {
3367        const Attribute* attribute = attributeItem(i);
3368        const Attribute* otherAttr = other->getAttributeItem(attribute->name());
3369        if (!otherAttr || attribute->value() != otherAttr->value())
3370            return false;
3371    }
3372
3373    return true;
3374}
3375
3376unsigned ElementData::getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
3377{
3378    // Continue to checking case-insensitively and/or full namespaced names if necessary:
3379    for (unsigned i = 0; i < length(); ++i) {
3380        const Attribute* attribute = attributeItem(i);
3381        if (!attribute->name().hasPrefix()) {
3382            if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute->localName()))
3383                return i;
3384        } else {
3385            // FIXME: Would be faster to do this comparison without calling toString, which
3386            // generates a temporary string by concatenation. But this branch is only reached
3387            // if the attribute name has a prefix, which is rare in HTML.
3388            if (equalPossiblyIgnoringCase(name, attribute->name().toString(), shouldIgnoreAttributeCase))
3389                return i;
3390        }
3391    }
3392    return attributeNotFound;
3393}
3394
3395unsigned ElementData::getAttributeItemIndexForAttributeNode(const Attr* attr) const
3396{
3397    ASSERT(attr);
3398    const Attribute* attributes = attributeBase();
3399    unsigned count = length();
3400    for (unsigned i = 0; i < count; ++i) {
3401        if (attributes[i].name() == attr->qualifiedName())
3402            return i;
3403    }
3404    return attributeNotFound;
3405}
3406
3407Attribute* UniqueElementData::getAttributeItem(const QualifiedName& name)
3408{
3409    unsigned count = length();
3410    for (unsigned i = 0; i < count; ++i) {
3411        if (m_attributeVector.at(i).name().matches(name))
3412            return &m_attributeVector.at(i);
3413    }
3414    return 0;
3415}
3416
3417Attribute* UniqueElementData::attributeItem(unsigned index)
3418{
3419    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
3420    return &m_attributeVector.at(index);
3421}
3422
3423} // namespace WebCore
3424