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