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