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