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