[Mac] Add support for MouseEvent.buttons
[WebKit-https.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-2017 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 "AttributeChangeInvalidation.h"
32 #include "CSSAnimationController.h"
33 #include "CSSParser.h"
34 #include "Chrome.h"
35 #include "ChromeClient.h"
36 #include "ClassChangeInvalidation.h"
37 #include "ComposedTreeAncestorIterator.h"
38 #include "ContainerNodeAlgorithms.h"
39 #include "CustomElementReactionQueue.h"
40 #include "CustomElementRegistry.h"
41 #include "DOMRect.h"
42 #include "DOMRectList.h"
43 #include "DOMTokenList.h"
44 #include "DocumentAnimation.h"
45 #include "DocumentSharedObjectPool.h"
46 #include "Editing.h"
47 #include "ElementIterator.h"
48 #include "ElementRareData.h"
49 #include "EventDispatcher.h"
50 #include "EventHandler.h"
51 #include "EventNames.h"
52 #include "FocusController.h"
53 #include "FocusEvent.h"
54 #include "FrameSelection.h"
55 #include "FrameView.h"
56 #include "HTMLBodyElement.h"
57 #include "HTMLCanvasElement.h"
58 #include "HTMLCollection.h"
59 #include "HTMLDocument.h"
60 #include "HTMLHtmlElement.h"
61 #include "HTMLLabelElement.h"
62 #include "HTMLNameCollection.h"
63 #include "HTMLObjectElement.h"
64 #include "HTMLOptGroupElement.h"
65 #include "HTMLOptionElement.h"
66 #include "HTMLParserIdioms.h"
67 #include "HTMLSelectElement.h"
68 #include "HTMLTemplateElement.h"
69 #include "IdChangeInvalidation.h"
70 #include "IdTargetObserverRegistry.h"
71 #include "InspectorInstrumentation.h"
72 #include "JSLazyEventListener.h"
73 #include "KeyboardEvent.h"
74 #include "KeyframeEffect.h"
75 #include "MainFrame.h"
76 #include "MutationObserverInterestGroup.h"
77 #include "MutationRecord.h"
78 #include "NoEventDispatchAssertion.h"
79 #include "NodeRenderStyle.h"
80 #include "PlatformWheelEvent.h"
81 #include "PointerLockController.h"
82 #include "RenderFragmentContainer.h"
83 #include "RenderLayer.h"
84 #include "RenderListBox.h"
85 #include "RenderTheme.h"
86 #include "RenderTreeUpdater.h"
87 #include "RenderView.h"
88 #include "RenderWidget.h"
89 #include "SVGDocumentExtensions.h"
90 #include "SVGElement.h"
91 #include "SVGNames.h"
92 #include "SVGSVGElement.h"
93 #include "ScrollLatchingState.h"
94 #include "SelectorQuery.h"
95 #include "Settings.h"
96 #include "SimulatedClick.h"
97 #include "SlotAssignment.h"
98 #include "StyleProperties.h"
99 #include "StyleResolver.h"
100 #include "StyleScope.h"
101 #include "StyleTreeResolver.h"
102 #include "TextIterator.h"
103 #include "VoidCallback.h"
104 #include "WheelEvent.h"
105 #include "XLinkNames.h"
106 #include "XMLNSNames.h"
107 #include "XMLNames.h"
108 #include "markup.h"
109 #include <wtf/CurrentTime.h>
110 #include <wtf/NeverDestroyed.h>
111 #include <wtf/text/CString.h>
112
113 namespace WebCore {
114
115 using namespace HTMLNames;
116 using namespace XMLNames;
117
118 static HashMap<Element*, Vector<RefPtr<Attr>>>& attrNodeListMap()
119 {
120     static NeverDestroyed<HashMap<Element*, Vector<RefPtr<Attr>>>> map;
121     return map;
122 }
123
124 static Vector<RefPtr<Attr>>* attrNodeListForElement(Element& element)
125 {
126     if (!element.hasSyntheticAttrChildNodes())
127         return nullptr;
128     ASSERT(attrNodeListMap().contains(&element));
129     return &attrNodeListMap().find(&element)->value;
130 }
131
132 static Vector<RefPtr<Attr>>& ensureAttrNodeListForElement(Element& element)
133 {
134     if (element.hasSyntheticAttrChildNodes()) {
135         ASSERT(attrNodeListMap().contains(&element));
136         return attrNodeListMap().find(&element)->value;
137     }
138     ASSERT(!attrNodeListMap().contains(&element));
139     element.setHasSyntheticAttrChildNodes(true);
140     return attrNodeListMap().add(&element, Vector<RefPtr<Attr>>()).iterator->value;
141 }
142
143 static void removeAttrNodeListForElement(Element& element)
144 {
145     ASSERT(element.hasSyntheticAttrChildNodes());
146     ASSERT(attrNodeListMap().contains(&element));
147     attrNodeListMap().remove(&element);
148     element.setHasSyntheticAttrChildNodes(false);
149 }
150
151 static Attr* findAttrNodeInList(Vector<RefPtr<Attr>>& attrNodeList, const QualifiedName& name)
152 {
153     for (auto& node : attrNodeList) {
154         if (node->qualifiedName().matches(name))
155             return node.get();
156     }
157     return nullptr;
158 }
159
160 static Attr* findAttrNodeInList(Vector<RefPtr<Attr>>& attrNodeList, const AtomicString& localName, bool shouldIgnoreAttributeCase)
161 {
162     const AtomicString& caseAdjustedName = shouldIgnoreAttributeCase ? localName.convertToASCIILowercase() : localName;
163     for (auto& node : attrNodeList) {
164         if (node->qualifiedName().localName() == caseAdjustedName)
165             return node.get();
166     }
167     return nullptr;
168 }
169
170 Ref<Element> Element::create(const QualifiedName& tagName, Document& document)
171 {
172     return adoptRef(*new Element(tagName, document, CreateElement));
173 }
174
175 Element::Element(const QualifiedName& tagName, Document& document, ConstructionType type)
176     : ContainerNode(document, type)
177     , m_tagName(tagName)
178 {
179 }
180
181 Element::~Element()
182 {
183     ASSERT(!beforePseudoElement());
184     ASSERT(!afterPseudoElement());
185
186     removeShadowRoot();
187
188     if (hasSyntheticAttrChildNodes())
189         detachAllAttrNodesFromElement();
190
191     if (hasPendingResources()) {
192         document().accessSVGExtensions().removeElementFromPendingResources(this);
193         ASSERT(!hasPendingResources());
194     }
195 }
196
197 inline ElementRareData* Element::elementRareData() const
198 {
199     ASSERT_WITH_SECURITY_IMPLICATION(hasRareData());
200     return static_cast<ElementRareData*>(rareData());
201 }
202
203 inline ElementRareData& Element::ensureElementRareData()
204 {
205     return static_cast<ElementRareData&>(ensureRareData());
206 }
207
208 void Element::clearTabIndexExplicitlyIfNeeded()
209 {
210     if (hasRareData())
211         elementRareData()->clearTabIndexExplicitly();
212 }
213
214 void Element::setTabIndexExplicitly(int tabIndex)
215 {
216     ensureElementRareData().setTabIndexExplicitly(tabIndex);
217 }
218
219 bool Element::tabIndexSetExplicitly() const
220 {
221     return hasRareData() && elementRareData()->tabIndexSetExplicitly();
222 }
223
224 bool Element::supportsFocus() const
225 {
226     return tabIndexSetExplicitly();
227 }
228
229 Element* Element::focusDelegate()
230 {
231     return this;
232 }
233
234 int Element::tabIndex() const
235 {
236     return hasRareData() ? elementRareData()->tabIndex() : 0;
237 }
238
239 void Element::setTabIndex(int value)
240 {
241     setIntegralAttribute(tabindexAttr, value);
242 }
243
244 bool Element::isKeyboardFocusable(KeyboardEvent&) const
245 {
246     return isFocusable() && tabIndex() >= 0;
247 }
248
249 bool Element::isMouseFocusable() const
250 {
251     return isFocusable();
252 }
253
254 bool Element::shouldUseInputMethod()
255 {
256     return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) != Editability::ReadOnly;
257 }
258
259 static bool isForceEvent(const PlatformMouseEvent& platformEvent)
260 {
261     return platformEvent.type() == PlatformEvent::MouseForceChanged || platformEvent.type() == PlatformEvent::MouseForceDown || platformEvent.type() == PlatformEvent::MouseForceUp;
262 }
263
264 bool Element::dispatchMouseEvent(const PlatformMouseEvent& platformEvent, const AtomicString& eventType, int detail, Element* relatedTarget)
265 {
266     if (isDisabledFormControl())
267         return false;
268
269     if (isForceEvent(platformEvent) && !document().hasListenerTypeForEventType(platformEvent.type()))
270         return false;
271
272     Ref<MouseEvent> mouseEvent = MouseEvent::create(eventType, document().defaultView(), platformEvent, detail, relatedTarget);
273
274     if (mouseEvent->type().isEmpty())
275         return true; // Shouldn't happen.
276
277     ASSERT(!mouseEvent->target() || mouseEvent->target() != relatedTarget);
278     bool didNotSwallowEvent = dispatchEvent(mouseEvent) && !mouseEvent->defaultHandled();
279
280     if (mouseEvent->type() == eventNames().clickEvent && mouseEvent->detail() == 2) {
281         // Special case: If it's a double click event, we also send the dblclick event. This is not part
282         // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
283         // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
284         Ref<MouseEvent> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
285             mouseEvent->bubbles(), mouseEvent->cancelable(), mouseEvent->view(), mouseEvent->detail(),
286             mouseEvent->screenX(), mouseEvent->screenY(), mouseEvent->clientX(), mouseEvent->clientY(),
287             mouseEvent->ctrlKey(), mouseEvent->altKey(), mouseEvent->shiftKey(), mouseEvent->metaKey(),
288             mouseEvent->button(), mouseEvent->buttons(), mouseEvent->syntheticClickType(), relatedTarget);
289
290         if (mouseEvent->defaultHandled())
291             doubleClickEvent->setDefaultHandled();
292
293         dispatchEvent(doubleClickEvent);
294         if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
295             return false;
296     }
297     return didNotSwallowEvent;
298 }
299
300
301 bool Element::dispatchWheelEvent(const PlatformWheelEvent& event)
302 {
303     Ref<WheelEvent> wheelEvent = WheelEvent::create(event, document().defaultView());
304
305     // Events with no deltas are important because they convey platform information about scroll gestures
306     // and momentum beginning or ending. However, those events should not be sent to the DOM since some
307     // websites will break. They need to be dispatched because dispatching them will call into the default
308     // event handler, and our platform code will correctly handle the phase changes. Calling stopPropogation()
309     // will prevent the event from being sent to the DOM, but will still call the default event handler.
310     if (!event.deltaX() && !event.deltaY())
311         wheelEvent->stopPropagation();
312
313     return EventDispatcher::dispatchEvent(*this, wheelEvent) && !wheelEvent->defaultHandled();
314 }
315
316 bool Element::dispatchKeyEvent(const PlatformKeyboardEvent& platformEvent)
317 {
318     Ref<KeyboardEvent> event = KeyboardEvent::create(platformEvent, document().defaultView());
319     if (Frame* frame = document().frame()) {
320         if (frame->eventHandler().accessibilityPreventsEventPropogation(event))
321             event->stopPropagation();
322     }
323     return EventDispatcher::dispatchEvent(*this, event) && !event->defaultHandled();
324 }
325
326 void Element::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickVisualOptions visualOptions)
327 {
328     simulateClick(*this, underlyingEvent, eventOptions, visualOptions, SimulatedClickSource::UserAgent);
329 }
330
331 Ref<Node> Element::cloneNodeInternal(Document& targetDocument, CloningOperation type)
332 {
333     switch (type) {
334     case CloningOperation::OnlySelf:
335     case CloningOperation::SelfWithTemplateContent:
336         return cloneElementWithoutChildren(targetDocument);
337     case CloningOperation::Everything:
338         break;
339     }
340     return cloneElementWithChildren(targetDocument);
341 }
342
343 Ref<Element> Element::cloneElementWithChildren(Document& targetDocument)
344 {
345     Ref<Element> clone = cloneElementWithoutChildren(targetDocument);
346     cloneChildNodes(clone);
347     return clone;
348 }
349
350 Ref<Element> Element::cloneElementWithoutChildren(Document& targetDocument)
351 {
352     Ref<Element> clone = cloneElementWithoutAttributesAndChildren(targetDocument);
353     // This will catch HTML elements in the wrong namespace that are not correctly copied.
354     // This is a sanity check as HTML overloads some of the DOM methods.
355     ASSERT(isHTMLElement() == clone->isHTMLElement());
356
357     clone->cloneDataFromElement(*this);
358     return clone;
359 }
360
361 Ref<Element> Element::cloneElementWithoutAttributesAndChildren(Document& targetDocument)
362 {
363     return targetDocument.createElement(tagQName(), false);
364 }
365
366 Ref<Attr> Element::detachAttribute(unsigned index)
367 {
368     ASSERT(elementData());
369
370     const Attribute& attribute = elementData()->attributeAt(index);
371
372     RefPtr<Attr> attrNode = attrIfExists(attribute.name());
373     if (attrNode)
374         detachAttrNodeFromElementWithValue(attrNode.get(), attribute.value());
375     else
376         attrNode = Attr::create(document(), attribute.name(), attribute.value());
377
378     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
379     return attrNode.releaseNonNull();
380 }
381
382 bool Element::removeAttribute(const QualifiedName& name)
383 {
384     if (!elementData())
385         return false;
386
387     unsigned index = elementData()->findAttributeIndexByName(name);
388     if (index == ElementData::attributeNotFound)
389         return false;
390
391     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
392     return true;
393 }
394
395 void Element::setBooleanAttribute(const QualifiedName& name, bool value)
396 {
397     if (value)
398         setAttribute(name, emptyAtom());
399     else
400         removeAttribute(name);
401 }
402
403 NamedNodeMap& Element::attributes() const
404 {
405     ElementRareData& rareData = const_cast<Element*>(this)->ensureElementRareData();
406     if (NamedNodeMap* attributeMap = rareData.attributeMap())
407         return *attributeMap;
408
409     rareData.setAttributeMap(std::make_unique<NamedNodeMap>(const_cast<Element&>(*this)));
410     return *rareData.attributeMap();
411 }
412
413 Node::NodeType Element::nodeType() const
414 {
415     return ELEMENT_NODE;
416 }
417
418 bool Element::hasAttribute(const QualifiedName& name) const
419 {
420     return hasAttributeNS(name.namespaceURI(), name.localName());
421 }
422
423 void Element::synchronizeAllAttributes() const
424 {
425     if (!elementData())
426         return;
427     if (elementData()->styleAttributeIsDirty()) {
428         ASSERT(isStyledElement());
429         static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
430     }
431
432     if (elementData()->animatedSVGAttributesAreDirty()) {
433         ASSERT(isSVGElement());
434         downcast<SVGElement>(*this).synchronizeAnimatedSVGAttribute(anyQName());
435     }
436 }
437
438 ALWAYS_INLINE void Element::synchronizeAttribute(const QualifiedName& name) const
439 {
440     if (!elementData())
441         return;
442     if (UNLIKELY(name == styleAttr && elementData()->styleAttributeIsDirty())) {
443         ASSERT_WITH_SECURITY_IMPLICATION(isStyledElement());
444         static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
445         return;
446     }
447
448     if (UNLIKELY(elementData()->animatedSVGAttributesAreDirty())) {
449         ASSERT(isSVGElement());
450         downcast<SVGElement>(*this).synchronizeAnimatedSVGAttribute(name);
451     }
452 }
453
454 static ALWAYS_INLINE bool isStyleAttribute(const Element& element, const AtomicString& attributeLocalName)
455 {
456     if (shouldIgnoreAttributeCase(element))
457         return equalLettersIgnoringASCIICase(attributeLocalName, "style");
458     return attributeLocalName == styleAttr.localName();
459 }
460
461 ALWAYS_INLINE void Element::synchronizeAttribute(const AtomicString& localName) const
462 {
463     // This version of synchronizeAttribute() is streamlined for the case where you don't have a full QualifiedName,
464     // e.g when called from DOM API.
465     if (!elementData())
466         return;
467     if (elementData()->styleAttributeIsDirty() && isStyleAttribute(*this, localName)) {
468         ASSERT_WITH_SECURITY_IMPLICATION(isStyledElement());
469         static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
470         return;
471     }
472     if (elementData()->animatedSVGAttributesAreDirty()) {
473         // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well.
474         ASSERT_WITH_SECURITY_IMPLICATION(isSVGElement());
475         downcast<SVGElement>(*this).synchronizeAnimatedSVGAttribute(QualifiedName(nullAtom(), localName, nullAtom()));
476     }
477 }
478
479 const AtomicString& Element::getAttribute(const QualifiedName& name) const
480 {
481     if (!elementData())
482         return nullAtom();
483     synchronizeAttribute(name);
484     if (const Attribute* attribute = findAttributeByName(name))
485         return attribute->value();
486     return nullAtom();
487 }
488
489 Vector<String> Element::getAttributeNames() const
490 {
491     Vector<String> attributesVector;
492     if (!hasAttributes())
493         return attributesVector;
494
495     auto attributes = attributesIterator();
496     attributesVector.reserveInitialCapacity(attributes.attributeCount());
497     for (auto& attribute : attributes)
498         attributesVector.uncheckedAppend(attribute.name().toString());
499     return attributesVector;
500 }
501
502 bool Element::isFocusable() const
503 {
504     if (!isConnected() || !supportsFocus())
505         return false;
506
507     if (!renderer()) {
508         // If the node is in a display:none tree it might say it needs style recalc but
509         // the whole document is actually up to date.
510         ASSERT(!needsStyleRecalc() || !document().childNeedsStyleRecalc());
511
512         // Elements in canvas fallback content are not rendered, but they are allowed to be
513         // focusable as long as their canvas is displayed and visible.
514         if (auto* canvas = ancestorsOfType<HTMLCanvasElement>(*this).first())
515             return canvas->renderer() && canvas->renderer()->style().visibility() == VISIBLE;
516     }
517
518     // FIXME: Even if we are not visible, we might have a child that is visible.
519     // Hyatt wants to fix that some day with a "has visible content" flag or the like.
520     if (!renderer() || renderer()->style().visibility() != VISIBLE)
521         return false;
522
523     return true;
524 }
525
526 bool Element::isUserActionElementInActiveChain() const
527 {
528     ASSERT(isUserActionElement());
529     return document().userActionElements().isInActiveChain(this);
530 }
531
532 bool Element::isUserActionElementActive() const
533 {
534     ASSERT(isUserActionElement());
535     return document().userActionElements().isActive(this);
536 }
537
538 bool Element::isUserActionElementFocused() const
539 {
540     ASSERT(isUserActionElement());
541     return document().userActionElements().isFocused(this);
542 }
543
544 bool Element::isUserActionElementHovered() const
545 {
546     ASSERT(isUserActionElement());
547     return document().userActionElements().isHovered(this);
548 }
549
550 void Element::setActive(bool flag, bool pause)
551 {
552     if (flag == active())
553         return;
554
555     document().userActionElements().setActive(this, flag);
556
557     const RenderStyle* renderStyle = this->renderStyle();
558     bool reactsToPress = (renderStyle && renderStyle->affectedByActive()) || styleAffectedByActive();
559     if (reactsToPress)
560         invalidateStyleForSubtree();
561
562     if (!renderer())
563         return;
564
565     if (renderer()->style().hasAppearance() && renderer()->theme().stateChanged(*renderer(), ControlStates::PressedState))
566         reactsToPress = true;
567
568     // The rest of this function implements a feature that only works if the
569     // platform supports immediate invalidations on the ChromeClient, so bail if
570     // that isn't supported.
571     if (!document().page()->chrome().client().supportsImmediateInvalidation())
572         return;
573
574     if (reactsToPress && pause) {
575         // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes
576         // to repaint the "down" state of the control is about the same time as it would take to repaint the
577         // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you
578         // leave this method, it will be about that long before the flush of the up state happens again).
579 #ifdef HAVE_FUNC_USLEEP
580         double startTime = monotonicallyIncreasingTime();
581 #endif
582
583         document().updateStyleIfNeeded();
584
585         // Do an immediate repaint.
586         if (renderer())
587             renderer()->repaint();
588
589         // FIXME: Come up with a less ridiculous way of doing this.
590 #ifdef HAVE_FUNC_USLEEP
591         // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
592         double remainingTime = 0.1 - (monotonicallyIncreasingTime() - startTime);
593         if (remainingTime > 0)
594             usleep(static_cast<useconds_t>(remainingTime * 1000000.0));
595 #endif
596     }
597 }
598
599 void Element::setFocus(bool flag)
600 {
601     if (flag == focused())
602         return;
603
604     document().userActionElements().setFocused(this, flag);
605     invalidateStyleForSubtree();
606
607     for (Element* element = this; element; element = element->parentElementInComposedTree())
608         element->setHasFocusWithin(flag);
609 }
610
611 void Element::setHovered(bool flag)
612 {
613     if (flag == hovered())
614         return;
615
616     document().userActionElements().setHovered(this, flag);
617
618     if (!renderer()) {
619         // When setting hover to false, the style needs to be recalc'd even when
620         // there's no renderer (imagine setting display:none in the :hover class,
621         // if a nil renderer would prevent this element from recalculating its
622         // style, it would never go back to its normal style and remain
623         // stuck in its hovered style).
624         if (!flag)
625             invalidateStyleForSubtree();
626
627         return;
628     }
629
630     if (renderer()->style().affectedByHover() || childrenAffectedByHover())
631         invalidateStyleForSubtree();
632
633     if (renderer()->style().hasAppearance())
634         renderer()->theme().stateChanged(*renderer(), ControlStates::HoverState);
635 }
636
637 void Element::scrollIntoView(bool alignToTop) 
638 {
639     document().updateLayoutIgnorePendingStylesheets();
640
641     if (!renderer())
642         return;
643
644     bool insideFixed;
645     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
646     // Align to the top / bottom and to the closest edge.
647     if (alignToTop)
648         renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
649     else
650         renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
651 }
652
653 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
654 {
655     document().updateLayoutIgnorePendingStylesheets();
656
657     if (!renderer())
658         return;
659
660     bool insideFixed;
661     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
662     if (centerIfNeeded)
663         renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
664     else
665         renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
666 }
667
668 void Element::scrollIntoViewIfNotVisible(bool centerIfNotVisible)
669 {
670     document().updateLayoutIgnorePendingStylesheets();
671     
672     if (!renderer())
673         return;
674     
675     bool insideFixed;
676     LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
677     if (centerIfNotVisible)
678         renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible);
679     else
680         renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, absoluteBounds, insideFixed, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible);
681 }
682
683 void Element::scrollBy(const ScrollToOptions& options)
684 {
685     return scrollBy(options.left.value_or(0), options.top.value_or(0));
686 }
687
688 static inline double normalizeNonFiniteValue(double f)
689 {
690     return std::isfinite(f) ? f : 0;
691 }
692
693 void Element::scrollBy(double x, double y)
694 {
695     scrollTo(scrollLeft() + normalizeNonFiniteValue(x), scrollTop() + normalizeNonFiniteValue(y));
696 }
697
698 void Element::scrollTo(const ScrollToOptions& options)
699 {
700     // If the element is the root element and document is in quirks mode, terminate these steps.
701     // Note that WebKit always uses quirks mode document scrolling behavior. See Document::scrollingElement().
702     if (this == document().documentElement())
703         return;
704
705     document().updateLayoutIgnorePendingStylesheets();
706
707     // If the element does not have any associated CSS layout box, the element has no associated scrolling box,
708     // or the element has no overflow, terminate these steps.
709     RenderBox* renderer = renderBox();
710     if (!renderer || !renderer->hasOverflowClip())
711         return;
712
713     // Normalize non-finite values for left and top dictionary members of options, if present.
714     double x = options.left ? normalizeNonFiniteValue(options.left.value()) : adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer);
715     double y = options.top ? normalizeNonFiniteValue(options.top.value()) : adjustForAbsoluteZoom(renderer->scrollTop(), *renderer);
716
717     renderer->setScrollLeft(clampToInteger(x * renderer->style().effectiveZoom()));
718     renderer->setScrollTop(clampToInteger(y * renderer->style().effectiveZoom()));
719 }
720
721 void Element::scrollTo(double x, double y)
722 {
723     scrollTo({ x, y });
724 }
725
726 void Element::scrollByUnits(int units, ScrollGranularity granularity)
727 {
728     document().updateLayoutIgnorePendingStylesheets();
729
730     auto* renderer = this->renderer();
731     if (!renderer)
732         return;
733
734     if (!renderer->hasOverflowClip())
735         return;
736
737     ScrollDirection direction = ScrollDown;
738     if (units < 0) {
739         direction = ScrollUp;
740         units = -units;
741     }
742     Element* stopElement = this;
743     downcast<RenderBox>(*renderer).scroll(direction, granularity, units, &stopElement);
744 }
745
746 void Element::scrollByLines(int lines)
747 {
748     scrollByUnits(lines, ScrollByLine);
749 }
750
751 void Element::scrollByPages(int pages)
752 {
753     scrollByUnits(pages, ScrollByPage);
754 }
755
756 static double localZoomForRenderer(const RenderElement& renderer)
757 {
758     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
759     // other out, but the alternative is that we'd have to crawl up the whole render tree every
760     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
761     double zoomFactor = 1;
762     if (renderer.style().effectiveZoom() != 1) {
763         // Need to find the nearest enclosing RenderElement that set up
764         // a differing zoom, and then we divide our result by it to eliminate the zoom.
765         const RenderElement* prev = &renderer;
766         for (RenderElement* curr = prev->parent(); curr; curr = curr->parent()) {
767             if (curr->style().effectiveZoom() != prev->style().effectiveZoom()) {
768                 zoomFactor = prev->style().zoom();
769                 break;
770             }
771             prev = curr;
772         }
773         if (prev->isRenderView())
774             zoomFactor = prev->style().zoom();
775     }
776     return zoomFactor;
777 }
778
779 static double adjustForLocalZoom(LayoutUnit value, const RenderElement& renderer, double& zoomFactor)
780 {
781     zoomFactor = localZoomForRenderer(renderer);
782     if (zoomFactor == 1)
783         return value.toDouble();
784     return value.toDouble() / zoomFactor;
785 }
786
787 enum LegacyCSSOMElementMetricsRoundingStrategy { Round, Floor };
788
789 static bool subpixelMetricsEnabled(const Document& document)
790 {
791     return document.settings().subpixelCSSOMElementMetricsEnabled();
792 }
793
794 static double convertToNonSubpixelValueIfNeeded(double value, const Document& document, LegacyCSSOMElementMetricsRoundingStrategy roundStrategy = Round)
795 {
796     return subpixelMetricsEnabled(document) ? value : roundStrategy == Round ? round(value) : floor(value);
797 }
798
799 double Element::offsetLeft()
800 {
801     document().updateLayoutIgnorePendingStylesheets();
802     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
803         LayoutUnit offsetLeft = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetLeft() : LayoutUnit(roundToInt(renderer->offsetLeft()));
804         double zoomFactor = 1;
805         double offsetLeftAdjustedWithZoom = adjustForLocalZoom(offsetLeft, *renderer, zoomFactor);
806         return convertToNonSubpixelValueIfNeeded(offsetLeftAdjustedWithZoom, renderer->document(), zoomFactor == 1 ? Floor : Round);
807     }
808     return 0;
809 }
810
811 double Element::offsetTop()
812 {
813     document().updateLayoutIgnorePendingStylesheets();
814     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
815         LayoutUnit offsetTop = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetTop() : LayoutUnit(roundToInt(renderer->offsetTop()));
816         double zoomFactor = 1;
817         double offsetTopAdjustedWithZoom = adjustForLocalZoom(offsetTop, *renderer, zoomFactor);
818         return convertToNonSubpixelValueIfNeeded(offsetTopAdjustedWithZoom, renderer->document(), zoomFactor == 1 ? Floor : Round);
819     }
820     return 0;
821 }
822
823 double Element::offsetWidth()
824 {
825     document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
826     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
827         LayoutUnit offsetWidth = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetWidth() : LayoutUnit(roundToInt(renderer->offsetWidth()));
828         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetWidth, *renderer).toDouble(), renderer->document());
829     }
830     return 0;
831 }
832
833 double Element::offsetHeight()
834 {
835     document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
836     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
837         LayoutUnit offsetHeight = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetHeight() : LayoutUnit(roundToInt(renderer->offsetHeight()));
838         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetHeight, *renderer).toDouble(), renderer->document());
839     }
840     return 0;
841 }
842
843 Element* Element::bindingsOffsetParent()
844 {
845     Element* element = offsetParent();
846     if (!element || !element->isInShadowTree())
847         return element;
848     return element->containingShadowRoot()->mode() == ShadowRootMode::UserAgent ? nullptr : element;
849 }
850
851 Element* Element::offsetParent()
852 {
853     document().updateLayoutIgnorePendingStylesheets();
854     auto renderer = this->renderer();
855     if (!renderer)
856         return nullptr;
857     auto offsetParent = renderer->offsetParent();
858     if (!offsetParent)
859         return nullptr;
860     return offsetParent->element();
861 }
862
863 double Element::clientLeft()
864 {
865     document().updateLayoutIgnorePendingStylesheets();
866
867     if (auto* renderer = renderBox()) {
868         LayoutUnit clientLeft = subpixelMetricsEnabled(renderer->document()) ? renderer->clientLeft() : LayoutUnit(roundToInt(renderer->clientLeft()));
869         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientLeft, *renderer).toDouble(), renderer->document());
870     }
871     return 0;
872 }
873
874 double Element::clientTop()
875 {
876     document().updateLayoutIgnorePendingStylesheets();
877
878     if (auto* renderer = renderBox()) {
879         LayoutUnit clientTop = subpixelMetricsEnabled(renderer->document()) ? renderer->clientTop() : LayoutUnit(roundToInt(renderer->clientTop()));
880         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientTop, *renderer).toDouble(), renderer->document());
881     }
882     return 0;
883 }
884
885 double Element::clientWidth()
886 {
887     document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
888
889     if (!document().hasLivingRenderTree())
890         return 0;
891
892     RenderView& renderView = *document().renderView();
893
894     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
895     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
896     bool inQuirksMode = document().inQuirksMode();
897     if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().bodyOrFrameset() == this))
898         return adjustForAbsoluteZoom(renderView.frameView().layoutWidth(), renderView);
899     
900     if (RenderBox* renderer = renderBox()) {
901         LayoutUnit clientWidth = subpixelMetricsEnabled(renderer->document()) ? renderer->clientWidth() : LayoutUnit(roundToInt(renderer->clientWidth()));
902         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientWidth, *renderer).toDouble(), renderer->document());
903     }
904     return 0;
905 }
906
907 double Element::clientHeight()
908 {
909     document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
910     if (!document().hasLivingRenderTree())
911         return 0;
912
913     RenderView& renderView = *document().renderView();
914
915     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
916     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
917     bool inQuirksMode = document().inQuirksMode();
918     if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().bodyOrFrameset() == this))
919         return adjustForAbsoluteZoom(renderView.frameView().layoutHeight(), renderView);
920
921     if (RenderBox* renderer = renderBox()) {
922         LayoutUnit clientHeight = subpixelMetricsEnabled(renderer->document()) ? renderer->clientHeight() : LayoutUnit(roundToInt(renderer->clientHeight()));
923         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(clientHeight, *renderer).toDouble(), renderer->document());
924     }
925     return 0;
926 }
927
928 int Element::scrollLeft()
929 {
930     document().updateLayoutIgnorePendingStylesheets();
931
932     if (auto* renderer = renderBox())
933         return adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer);
934     return 0;
935 }
936
937 int Element::scrollTop()
938 {
939     document().updateLayoutIgnorePendingStylesheets();
940
941     if (RenderBox* renderer = renderBox())
942         return adjustForAbsoluteZoom(renderer->scrollTop(), *renderer);
943     return 0;
944 }
945
946 void Element::setScrollLeft(int newLeft)
947 {
948     document().updateLayoutIgnorePendingStylesheets();
949
950     if (auto* renderer = renderBox()) {
951         renderer->setScrollLeft(static_cast<int>(newLeft * renderer->style().effectiveZoom()));
952         if (auto* scrollableArea = renderer->layer())
953             scrollableArea->setScrolledProgrammatically(true);
954     }
955 }
956
957 void Element::setScrollTop(int newTop)
958 {
959     document().updateLayoutIgnorePendingStylesheets();
960
961     if (auto* renderer = renderBox()) {
962         renderer->setScrollTop(static_cast<int>(newTop * renderer->style().effectiveZoom()));
963         if (auto* scrollableArea = renderer->layer())
964             scrollableArea->setScrolledProgrammatically(true);
965     }
966 }
967
968 int Element::scrollWidth()
969 {
970     document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
971     if (auto* renderer = renderBox())
972         return adjustForAbsoluteZoom(renderer->scrollWidth(), *renderer);
973     return 0;
974 }
975
976 int Element::scrollHeight()
977 {
978     document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
979     if (auto* renderer = renderBox())
980         return adjustForAbsoluteZoom(renderer->scrollHeight(), *renderer);
981     return 0;
982 }
983
984 IntRect Element::boundsInRootViewSpace()
985 {
986     document().updateLayoutIgnorePendingStylesheets();
987
988     FrameView* view = document().view();
989     if (!view)
990         return IntRect();
991
992     Vector<FloatQuad> quads;
993
994     if (isSVGElement() && renderer()) {
995         // Get the bounding rectangle from the SVG model.
996         SVGElement& svgElement = downcast<SVGElement>(*this);
997         FloatRect localRect;
998         if (svgElement.getBoundingBox(localRect))
999             quads.append(renderer()->localToAbsoluteQuad(localRect));
1000     } else {
1001         // Get the bounding rectangle from the box model.
1002         if (renderBoxModelObject())
1003             renderBoxModelObject()->absoluteQuads(quads);
1004     }
1005
1006     if (quads.isEmpty())
1007         return IntRect();
1008
1009     IntRect result = quads[0].enclosingBoundingBox();
1010     for (size_t i = 1; i < quads.size(); ++i)
1011         result.unite(quads[i].enclosingBoundingBox());
1012
1013     result = view->contentsToRootView(result);
1014     return result;
1015 }
1016
1017 static bool layoutOverflowRectContainsAllDescendants(const RenderBox& renderBox)
1018 {
1019     if (renderBox.isRenderView())
1020         return true;
1021
1022     if (!renderBox.element())
1023         return false;
1024
1025     // If there are any position:fixed inside of us, game over.
1026     if (auto* viewPositionedObjects = renderBox.view().positionedObjects()) {
1027         for (auto* positionedBox : *viewPositionedObjects) {
1028             if (positionedBox == &renderBox)
1029                 continue;
1030             if (positionedBox->style().position() == FixedPosition && renderBox.element()->contains(positionedBox->element()))
1031                 return false;
1032         }
1033     }
1034
1035     if (renderBox.canContainAbsolutelyPositionedObjects()) {
1036         // Our layout overflow will include all descendant positioned elements.
1037         return true;
1038     }
1039
1040     // This renderer may have positioned descendants whose containing block is some ancestor.
1041     if (auto* containingBlock = renderBox.containingBlockForAbsolutePosition()) {
1042         if (auto* positionedObjects = containingBlock->positionedObjects()) {
1043             for (auto* positionedBox : *positionedObjects) {
1044                 if (positionedBox == &renderBox)
1045                     continue;
1046                 if (renderBox.element()->contains(positionedBox->element()))
1047                     return false;
1048             }
1049         }
1050     }
1051     return false;
1052 }
1053
1054 LayoutRect Element::absoluteEventBounds(bool& boundsIncludeAllDescendantElements, bool& includesFixedPositionElements)
1055 {
1056     boundsIncludeAllDescendantElements = false;
1057     includesFixedPositionElements = false;
1058
1059     if (!renderer())
1060         return LayoutRect();
1061
1062     LayoutRect result;
1063     if (isSVGElement()) {
1064         // Get the bounding rectangle from the SVG model.
1065         SVGElement& svgElement = downcast<SVGElement>(*this);
1066         FloatRect localRect;
1067         if (svgElement.getBoundingBox(localRect, SVGLocatable::DisallowStyleUpdate))
1068             result = LayoutRect(renderer()->localToAbsoluteQuad(localRect, UseTransforms, &includesFixedPositionElements).boundingBox());
1069     } else {
1070         auto* renderer = this->renderer();
1071         if (is<RenderBox>(renderer)) {
1072             auto& box = downcast<RenderBox>(*renderer);
1073
1074             bool computedBounds = false;
1075             
1076             if (RenderFragmentedFlow* fragmentedFlow = box.enclosingFragmentedFlow()) {
1077                 bool wasFixed = false;
1078                 Vector<FloatQuad> quads;
1079                 FloatRect localRect(0, 0, box.width(), box.height());
1080                 if (fragmentedFlow->absoluteQuadsForBox(quads, &wasFixed, &box, localRect.y(), localRect.maxY())) {
1081                     FloatRect quadBounds = quads[0].boundingBox();
1082                     for (size_t i = 1; i < quads.size(); ++i)
1083                         quadBounds.unite(quads[i].boundingBox());
1084                     
1085                     result = LayoutRect(quadBounds);
1086                     computedBounds = true;
1087                 } else {
1088                     // Probably columns. Just return the bounds of the multicol block for now.
1089                     // FIXME: this doesn't handle nested columns.
1090                     RenderElement* multicolContainer = fragmentedFlow->parent();
1091                     if (multicolContainer && is<RenderBox>(multicolContainer)) {
1092                         auto overflowRect = downcast<RenderBox>(*multicolContainer).layoutOverflowRect();
1093                         result = LayoutRect(multicolContainer->localToAbsoluteQuad(FloatRect(overflowRect), UseTransforms, &includesFixedPositionElements).boundingBox());
1094                         computedBounds = true;
1095                     }
1096                 }
1097             }
1098
1099             if (!computedBounds) {
1100                 LayoutRect overflowRect = box.layoutOverflowRect();
1101                 result = LayoutRect(box.localToAbsoluteQuad(FloatRect(overflowRect), UseTransforms, &includesFixedPositionElements).boundingBox());
1102                 boundsIncludeAllDescendantElements = layoutOverflowRectContainsAllDescendants(box);
1103             }
1104         } else
1105             result = LayoutRect(renderer->absoluteBoundingBoxRect(true /* useTransforms */, &includesFixedPositionElements));
1106     }
1107
1108     return result;
1109 }
1110
1111 LayoutRect Element::absoluteEventBoundsOfElementAndDescendants(bool& includesFixedPositionElements)
1112 {
1113     bool boundsIncludeDescendants;
1114     LayoutRect result = absoluteEventBounds(boundsIncludeDescendants, includesFixedPositionElements);
1115     if (boundsIncludeDescendants)
1116         return result;
1117
1118     for (auto& child : childrenOfType<Element>(*this)) {
1119         bool includesFixedPosition = false;
1120         LayoutRect childBounds = child.absoluteEventBoundsOfElementAndDescendants(includesFixedPosition);
1121         includesFixedPositionElements |= includesFixedPosition;
1122         result.unite(childBounds);
1123     }
1124
1125     return result;
1126 }
1127
1128 LayoutRect Element::absoluteEventHandlerBounds(bool& includesFixedPositionElements)
1129 {
1130     // This is not web-exposed, so don't call the FOUC-inducing updateLayoutIgnorePendingStylesheets().
1131     FrameView* frameView = document().view();
1132     if (!frameView)
1133         return LayoutRect();
1134
1135     if (frameView->needsLayout())
1136         frameView->layout();
1137
1138     return absoluteEventBoundsOfElementAndDescendants(includesFixedPositionElements);
1139 }
1140
1141 static std::optional<std::pair<RenderObject*, LayoutRect>> listBoxElementBoundingBox(Element& element)
1142 {
1143     HTMLSelectElement* selectElement;
1144     bool isGroup;
1145     if (is<HTMLOptionElement>(element)) {
1146         selectElement = downcast<HTMLOptionElement>(element).ownerSelectElement();
1147         isGroup = false;
1148     } else if (is<HTMLOptGroupElement>(element)) {
1149         selectElement = downcast<HTMLOptGroupElement>(element).ownerSelectElement();
1150         isGroup = true;
1151     } else
1152         return std::nullopt;
1153
1154     if (!selectElement || !selectElement->renderer() || !is<RenderListBox>(selectElement->renderer()))
1155         return std::nullopt;
1156
1157     auto& renderer = downcast<RenderListBox>(*selectElement->renderer());
1158     std::optional<LayoutRect> boundingBox;
1159     int optionIndex = 0;
1160     for (auto* item : selectElement->listItems()) {
1161         if (item == &element) {
1162             LayoutPoint additionOffset;
1163             boundingBox = renderer.itemBoundingBoxRect(additionOffset, optionIndex);
1164             if (!isGroup)
1165                 break;
1166         } else if (isGroup && boundingBox) {
1167             if (item->parentNode() != &element)
1168                 break;
1169             LayoutPoint additionOffset;
1170             boundingBox->setHeight(boundingBox->height() + renderer.itemBoundingBoxRect(additionOffset, optionIndex).height());
1171         }
1172         ++optionIndex;
1173     }
1174
1175     if (!boundingBox)
1176         return std::nullopt;
1177
1178     return std::pair<RenderObject*, LayoutRect> { &renderer, boundingBox.value() };
1179 }
1180
1181 Ref<DOMRectList> Element::getClientRects()
1182 {
1183     document().updateLayoutIgnorePendingStylesheets();
1184
1185     RenderObject* renderer = this->renderer();
1186     Vector<FloatQuad> quads;
1187
1188     if (auto pair = listBoxElementBoundingBox(*this)) {
1189         renderer = pair.value().first;
1190         quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
1191     } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
1192         renderBoxModelObject->absoluteQuads(quads);
1193
1194     // FIXME: Handle SVG elements.
1195     // FIXME: Handle table/inline-table with a caption.
1196
1197     if (quads.isEmpty())
1198         return DOMRectList::create();
1199
1200     document().convertAbsoluteToClientQuads(quads, renderer->style());
1201     return DOMRectList::create(quads);
1202 }
1203
1204 FloatRect Element::boundingClientRect()
1205 {
1206     document().updateLayoutIgnorePendingStylesheets();
1207
1208     RenderObject* renderer = this->renderer();
1209     Vector<FloatQuad> quads;
1210     if (isSVGElement() && renderer && !renderer->isSVGRoot()) {
1211         // Get the bounding rectangle from the SVG model.
1212         SVGElement& svgElement = downcast<SVGElement>(*this);
1213         FloatRect localRect;
1214         if (svgElement.getBoundingBox(localRect))
1215             quads.append(renderer->localToAbsoluteQuad(localRect));
1216     } else if (auto pair = listBoxElementBoundingBox(*this)) {
1217         renderer = pair.value().first;
1218         quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
1219     } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
1220         renderBoxModelObject->absoluteQuads(quads);
1221
1222     if (quads.isEmpty())
1223         return { };
1224
1225     FloatRect result = quads[0].boundingBox();
1226     for (size_t i = 1; i < quads.size(); ++i)
1227         result.unite(quads[i].boundingBox());
1228
1229     document().convertAbsoluteToClientRect(result, renderer->style());
1230     return result;
1231 }
1232
1233 Ref<DOMRect> Element::getBoundingClientRect()
1234 {
1235     return DOMRect::create(boundingClientRect());
1236 }
1237
1238 // Note that this is not web-exposed, and does not use the same coordinate system as getBoundingClientRect() and friends.
1239 IntRect Element::clientRect() const
1240 {
1241     if (RenderObject* renderer = this->renderer())
1242         return document().view()->contentsToRootView(renderer->absoluteBoundingBoxRect());
1243     return IntRect();
1244 }
1245     
1246 IntRect Element::screenRect() const
1247 {
1248     if (RenderObject* renderer = this->renderer())
1249         return document().view()->contentsToScreen(renderer->absoluteBoundingBoxRect());
1250     return IntRect();
1251 }
1252
1253 const AtomicString& Element::getAttribute(const AtomicString& localName) const
1254 {
1255     if (!elementData())
1256         return nullAtom();
1257     synchronizeAttribute(localName);
1258     if (const Attribute* attribute = elementData()->findAttributeByName(localName, shouldIgnoreAttributeCase(*this)))
1259         return attribute->value();
1260     return nullAtom();
1261 }
1262
1263 const AtomicString& Element::getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
1264 {
1265     return getAttribute(QualifiedName(nullAtom(), localName, namespaceURI));
1266 }
1267
1268 ExceptionOr<void> Element::setAttribute(const AtomicString& localName, const AtomicString& value)
1269 {
1270     if (!Document::isValidName(localName))
1271         return Exception { InvalidCharacterError };
1272
1273     synchronizeAttribute(localName);
1274     auto caseAdjustedLocalName = shouldIgnoreAttributeCase(*this) ? localName.convertToASCIILowercase() : localName;
1275     unsigned index = elementData() ? elementData()->findAttributeIndexByName(caseAdjustedLocalName, false) : ElementData::attributeNotFound;
1276     auto name = index != ElementData::attributeNotFound ? attributeAt(index).name() : QualifiedName { nullAtom(), caseAdjustedLocalName, nullAtom() };
1277     setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
1278
1279     return { };
1280 }
1281
1282 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
1283 {
1284     synchronizeAttribute(name);
1285     unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
1286     setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
1287 }
1288
1289 void Element::setAttributeWithoutSynchronization(const QualifiedName& name, const AtomicString& value)
1290 {
1291     unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
1292     setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
1293 }
1294
1295 void Element::setSynchronizedLazyAttribute(const QualifiedName& name, const AtomicString& value)
1296 {
1297     unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
1298     setAttributeInternal(index, name, value, InSynchronizationOfLazyAttribute);
1299 }
1300
1301 inline void Element::setAttributeInternal(unsigned index, const QualifiedName& name, const AtomicString& newValue, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
1302 {
1303     if (newValue.isNull()) {
1304         if (index != ElementData::attributeNotFound)
1305             removeAttributeInternal(index, inSynchronizationOfLazyAttribute);
1306         return;
1307     }
1308
1309     if (index == ElementData::attributeNotFound) {
1310         addAttributeInternal(name, newValue, inSynchronizationOfLazyAttribute);
1311         return;
1312     }
1313
1314     if (inSynchronizationOfLazyAttribute) {
1315         ensureUniqueElementData().attributeAt(index).setValue(newValue);
1316         return;
1317     }
1318
1319     const Attribute& attribute = attributeAt(index);
1320     QualifiedName attributeName = attribute.name();
1321     AtomicString oldValue = attribute.value();
1322
1323     willModifyAttribute(attributeName, oldValue, newValue);
1324
1325     if (newValue != oldValue) {
1326         Style::AttributeChangeInvalidation styleInvalidation(*this, name, oldValue, newValue);
1327         ensureUniqueElementData().attributeAt(index).setValue(newValue);
1328     }
1329
1330     didModifyAttribute(attributeName, oldValue, newValue);
1331 }
1332
1333 static inline AtomicString makeIdForStyleResolution(const AtomicString& value, bool inQuirksMode)
1334 {
1335     if (inQuirksMode)
1336         return value.convertToASCIILowercase();
1337     return value;
1338 }
1339
1340 void Element::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
1341 {
1342     bool valueIsSameAsBefore = oldValue == newValue;
1343
1344     if (!valueIsSameAsBefore) {
1345         if (name == HTMLNames::idAttr) {
1346             if (!oldValue.isEmpty())
1347                 treeScope().idTargetObserverRegistry().notifyObservers(*oldValue.impl());
1348             if (!newValue.isEmpty())
1349                 treeScope().idTargetObserverRegistry().notifyObservers(*newValue.impl());
1350
1351             AtomicString oldId = elementData()->idForStyleResolution();
1352             AtomicString newId = makeIdForStyleResolution(newValue, document().inQuirksMode());
1353             if (newId != oldId) {
1354                 Style::IdChangeInvalidation styleInvalidation(*this, oldId, newId);
1355                 elementData()->setIdForStyleResolution(newId);
1356             }
1357         } else if (name == classAttr)
1358             classAttributeChanged(newValue);
1359         else if (name == HTMLNames::nameAttr)
1360             elementData()->setHasNameAttribute(!newValue.isNull());
1361         else if (name == HTMLNames::pseudoAttr) {
1362             if (needsStyleInvalidation() && isInShadowTree())
1363                 invalidateStyleForSubtree();
1364         }
1365         else if (name == HTMLNames::slotAttr) {
1366             if (auto* parent = parentElement()) {
1367                 if (auto* shadowRoot = parent->shadowRoot())
1368                     shadowRoot->hostChildElementDidChangeSlotAttribute(*this, oldValue, newValue);
1369             }
1370         }
1371     }
1372
1373     parseAttribute(name, newValue);
1374
1375     document().incDOMTreeVersion();
1376
1377     if (UNLIKELY(isDefinedCustomElement()))
1378         CustomElementReactionQueue::enqueueAttributeChangedCallbackIfNeeded(*this, name, oldValue, newValue);
1379
1380     if (valueIsSameAsBefore)
1381         return;
1382
1383     invalidateNodeListAndCollectionCachesInAncestorsForAttribute(name);
1384
1385     if (AXObjectCache* cache = document().existingAXObjectCache())
1386         cache->handleAttributeChanged(name, this);
1387 }
1388
1389 template <typename CharacterType>
1390 static inline bool classStringHasClassName(const CharacterType* characters, unsigned length)
1391 {
1392     ASSERT(length > 0);
1393
1394     unsigned i = 0;
1395     do {
1396         if (isNotHTMLSpace(characters[i]))
1397             break;
1398         ++i;
1399     } while (i < length);
1400
1401     return i < length;
1402 }
1403
1404 static inline bool classStringHasClassName(const AtomicString& newClassString)
1405 {
1406     unsigned length = newClassString.length();
1407
1408     if (!length)
1409         return false;
1410
1411     if (newClassString.is8Bit())
1412         return classStringHasClassName(newClassString.characters8(), length);
1413     return classStringHasClassName(newClassString.characters16(), length);
1414 }
1415
1416 void Element::classAttributeChanged(const AtomicString& newClassString)
1417 {
1418     // Note: We'll need ElementData, but it doesn't have to be UniqueElementData.
1419     if (!elementData())
1420         ensureUniqueElementData();
1421
1422     bool shouldFoldCase = document().inQuirksMode();
1423     bool newStringHasClasses = classStringHasClassName(newClassString);
1424
1425     auto oldClassNames = elementData()->classNames();
1426     auto newClassNames = newStringHasClasses ? SpaceSplitString(newClassString, shouldFoldCase) : SpaceSplitString();
1427     {
1428         Style::ClassChangeInvalidation styleInvalidation(*this, oldClassNames, newClassNames);
1429         elementData()->setClassNames(newClassNames);
1430     }
1431
1432     if (hasRareData()) {
1433         if (auto* classList = elementRareData()->classList())
1434             classList->associatedAttributeValueChanged(newClassString);
1435     }
1436 }
1437
1438 URL Element::absoluteLinkURL() const
1439 {
1440     if (!isLink())
1441         return URL();
1442
1443     AtomicString linkAttribute;
1444     if (hasTagName(SVGNames::aTag))
1445         linkAttribute = getAttribute(XLinkNames::hrefAttr);
1446     else
1447         linkAttribute = getAttribute(HTMLNames::hrefAttr);
1448
1449     if (linkAttribute.isEmpty())
1450         return URL();
1451
1452     return document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkAttribute));
1453 }
1454
1455 #if ENABLE(TOUCH_EVENTS)
1456 bool Element::allowsDoubleTapGesture() const
1457 {
1458     if (renderStyle() && renderStyle()->touchAction() != TouchAction::Auto)
1459         return false;
1460
1461     Element* parent = parentElement();
1462     return !parent || parent->allowsDoubleTapGesture();
1463 }
1464 #endif
1465
1466 StyleResolver& Element::styleResolver()
1467 {
1468     if (auto* shadowRoot = containingShadowRoot())
1469         return shadowRoot->styleScope().resolver();
1470
1471     return document().styleScope().resolver();
1472 }
1473
1474 ElementStyle Element::resolveStyle(const RenderStyle* parentStyle)
1475 {
1476     return styleResolver().styleForElement(*this, parentStyle);
1477 }
1478
1479 void Element::invalidateStyle()
1480 {
1481     Node::invalidateStyle(Style::Validity::ElementInvalid);
1482 }
1483
1484 void Element::invalidateStyleAndLayerComposition()
1485 {
1486     Node::invalidateStyle(Style::Validity::ElementInvalid, Style::InvalidationMode::RecompositeLayer);
1487 }
1488
1489 void Element::invalidateStyleForSubtree()
1490 {
1491     Node::invalidateStyle(Style::Validity::SubtreeInvalid);
1492 }
1493
1494 void Element::invalidateStyleAndRenderersForSubtree()
1495 {
1496     Node::invalidateStyle(Style::Validity::SubtreeAndRenderersInvalid);
1497 }
1498
1499 #if ENABLE(WEB_ANIMATIONS)
1500 WebAnimationVector Element::getAnimations()
1501 {
1502     auto checkTarget = [this](AnimationEffect const& effect)
1503     {
1504         return (static_cast<KeyframeEffect const&>(effect).target() == this);
1505     };
1506
1507     auto* document = DocumentAnimation::from(&this->document());
1508     if (document)
1509         return document->getAnimations(WTFMove(checkTarget));
1510     return WebAnimationVector();
1511 }
1512 #endif
1513
1514 bool Element::hasDisplayContents() const
1515 {
1516     if (renderer() || !hasRareData())
1517         return false;
1518     const RenderStyle* style = elementRareData()->computedStyle();
1519     return style && style->display() == CONTENTS;
1520 }
1521
1522 void Element::storeDisplayContentsStyle(std::unique_ptr<RenderStyle> style)
1523 {
1524     ASSERT(style && style->display() == CONTENTS);
1525     ASSERT(!renderer());
1526     ensureElementRareData().setComputedStyle(WTFMove(style));
1527 }
1528
1529 // Returns true is the given attribute is an event handler.
1530 // We consider an event handler any attribute that begins with "on".
1531 // It is a simple solution that has the advantage of not requiring any
1532 // code or configuration change if a new event handler is defined.
1533
1534 static inline bool isEventHandlerAttribute(const Attribute& attribute)
1535 {
1536     return attribute.name().namespaceURI().isNull() && attribute.name().localName().startsWith("on");
1537 }
1538
1539 bool Element::isJavaScriptURLAttribute(const Attribute& attribute) const
1540 {
1541     return isURLAttribute(attribute) && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(attribute.value()));
1542 }
1543
1544 void Element::stripScriptingAttributes(Vector<Attribute>& attributeVector) const
1545 {
1546     attributeVector.removeAllMatching([this](auto& attribute) -> bool {
1547         return isEventHandlerAttribute(attribute)
1548             || this->isJavaScriptURLAttribute(attribute)
1549             || this->isHTMLContentAttribute(attribute);
1550     });
1551 }
1552
1553 void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
1554 {
1555     ASSERT(!isConnected());
1556     ASSERT(!parentNode());
1557     ASSERT(!m_elementData);
1558
1559     if (!attributeVector.isEmpty()) {
1560         if (document().sharedObjectPool())
1561             m_elementData = document().sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector);
1562         else
1563             m_elementData = ShareableElementData::createWithAttributes(attributeVector);
1564
1565     }
1566
1567     parserDidSetAttributes();
1568
1569     // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData.
1570     for (const auto& attribute : attributeVector)
1571         attributeChanged(attribute.name(), nullAtom(), attribute.value(), ModifiedDirectly);
1572 }
1573
1574 void Element::parserDidSetAttributes()
1575 {
1576 }
1577
1578 void Element::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
1579 {
1580     ASSERT_WITH_SECURITY_IMPLICATION(&document() == &newDocument);
1581     Node::didMoveToNewDocument(oldDocument, newDocument);
1582
1583     if (oldDocument.inQuirksMode() != document().inQuirksMode()) {
1584         // ElementData::m_classNames or ElementData::m_idForStyleResolution need to be updated with the right case.
1585         if (hasID())
1586             attributeChanged(idAttr, nullAtom(), getIdAttribute());
1587         if (hasClass())
1588             attributeChanged(classAttr, nullAtom(), getAttribute(classAttr));
1589     }
1590
1591     if (UNLIKELY(isDefinedCustomElement()))
1592         CustomElementReactionQueue::enqueueAdoptedCallbackIfNeeded(*this, oldDocument, newDocument);
1593 }
1594
1595 bool Element::hasAttributes() const
1596 {
1597     synchronizeAllAttributes();
1598     return elementData() && elementData()->length();
1599 }
1600
1601 bool Element::hasEquivalentAttributes(const Element* other) const
1602 {
1603     synchronizeAllAttributes();
1604     other->synchronizeAllAttributes();
1605     if (elementData() == other->elementData())
1606         return true;
1607     if (elementData())
1608         return elementData()->isEquivalent(other->elementData());
1609     if (other->elementData())
1610         return other->elementData()->isEquivalent(elementData());
1611     return true;
1612 }
1613
1614 String Element::nodeName() const
1615 {
1616     return m_tagName.toString();
1617 }
1618
1619 String Element::nodeNamePreservingCase() const
1620 {
1621     return m_tagName.toString();
1622 }
1623
1624 ExceptionOr<void> Element::setPrefix(const AtomicString& prefix)
1625 {
1626     auto result = checkSetPrefix(prefix);
1627     if (result.hasException())
1628         return result.releaseException();
1629
1630     m_tagName.setPrefix(prefix.isEmpty() ? nullAtom() : prefix);
1631     return { };
1632 }
1633
1634 const AtomicString& Element::imageSourceURL() const
1635 {
1636     return attributeWithoutSynchronization(srcAttr);
1637 }
1638
1639 bool Element::rendererIsNeeded(const RenderStyle& style)
1640 {
1641     return style.display() != NONE && style.display() != CONTENTS;
1642 }
1643
1644 RenderPtr<RenderElement> Element::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
1645 {
1646     return RenderElement::createFor(*this, WTFMove(style));
1647 }
1648
1649 Node::InsertionNotificationRequest Element::insertedInto(ContainerNode& insertionPoint)
1650 {
1651     bool wasInDocument = isConnected();
1652     // need to do superclass processing first so isConnected() is true
1653     // by the time we reach updateId
1654     ContainerNode::insertedInto(insertionPoint);
1655     ASSERT(!wasInDocument || isConnected());
1656
1657 #if ENABLE(FULLSCREEN_API)
1658     if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
1659         setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
1660 #endif
1661
1662     if (parentNode() == &insertionPoint) {
1663         if (auto* shadowRoot = parentNode()->shadowRoot())
1664             shadowRoot->hostChildElementDidChange(*this);
1665     }
1666
1667     if (!insertionPoint.isInTreeScope())
1668         return InsertionDone;
1669
1670     // This function could be called when this element's shadow root's host or its ancestor is inserted.
1671     // This element is new to the shadow tree (and its tree scope) only if the parent into which this element
1672     // or its ancestor is inserted belongs to the same tree scope as this element's.
1673     TreeScope* newScope = &insertionPoint.treeScope();
1674     bool becomeConnected = !wasInDocument && isConnected();
1675     HTMLDocument* newDocument = becomeConnected && is<HTMLDocument>(newScope->documentScope()) ? &downcast<HTMLDocument>(newScope->documentScope()) : nullptr;
1676     if (newScope != &treeScope())
1677         newScope = nullptr;
1678
1679     const AtomicString& idValue = getIdAttribute();
1680     if (!idValue.isNull()) {
1681         if (newScope)
1682             updateIdForTreeScope(*newScope, nullAtom(), idValue);
1683         if (newDocument)
1684             updateIdForDocument(*newDocument, nullAtom(), idValue, AlwaysUpdateHTMLDocumentNamedItemMaps);
1685     }
1686
1687     const AtomicString& nameValue = getNameAttribute();
1688     if (!nameValue.isNull()) {
1689         if (newScope)
1690             updateNameForTreeScope(*newScope, nullAtom(), nameValue);
1691         if (newDocument)
1692             updateNameForDocument(*newDocument, nullAtom(), nameValue);
1693     }
1694
1695     if (newScope && hasTagName(labelTag)) {
1696         if (newScope->shouldCacheLabelsByForAttribute())
1697             updateLabel(*newScope, nullAtom(), attributeWithoutSynchronization(forAttr));
1698     }
1699
1700     if (becomeConnected) {
1701         if (UNLIKELY(isCustomElementUpgradeCandidate()))
1702             CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this);
1703         if (UNLIKELY(isDefinedCustomElement()))
1704             CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
1705     }
1706
1707     return InsertionDone;
1708 }
1709
1710 void Element::removedFrom(ContainerNode& insertionPoint)
1711 {
1712 #if ENABLE(FULLSCREEN_API)
1713     if (containsFullScreenElement())
1714         setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
1715 #endif
1716 #if ENABLE(POINTER_LOCK)
1717     if (document().page())
1718         document().page()->pointerLockController().elementRemoved(*this);
1719 #endif
1720
1721     setSavedLayerScrollPosition(ScrollPosition());
1722
1723     if (insertionPoint.isInTreeScope()) {
1724         TreeScope* oldScope = &insertionPoint.treeScope();
1725         bool becomeDisconnected = isConnected();
1726         HTMLDocument* oldDocument = becomeDisconnected && is<HTMLDocument>(oldScope->documentScope()) ? &downcast<HTMLDocument>(oldScope->documentScope()) : nullptr;
1727
1728         // ContainerNode::removeBetween always sets the removed chid's tree scope to Document's but InTreeScope flag is unset in Node::removedFrom.
1729         // So this element has been removed from the old tree scope only if InTreeScope flag is set and this element's tree scope is Document's.
1730         if (!isInTreeScope() || &treeScope() != &document())
1731             oldScope = nullptr;
1732
1733         const AtomicString& idValue = getIdAttribute();
1734         if (!idValue.isNull()) {
1735             if (oldScope)
1736                 updateIdForTreeScope(*oldScope, idValue, nullAtom());
1737             if (oldDocument)
1738                 updateIdForDocument(*oldDocument, idValue, nullAtom(), AlwaysUpdateHTMLDocumentNamedItemMaps);
1739         }
1740
1741         const AtomicString& nameValue = getNameAttribute();
1742         if (!nameValue.isNull()) {
1743             if (oldScope)
1744                 updateNameForTreeScope(*oldScope, nameValue, nullAtom());
1745             if (oldDocument)
1746                 updateNameForDocument(*oldDocument, nameValue, nullAtom());
1747         }
1748
1749         if (oldScope && hasTagName(labelTag)) {
1750             if (oldScope->shouldCacheLabelsByForAttribute())
1751                 updateLabel(*oldScope, attributeWithoutSynchronization(forAttr), nullAtom());
1752         }
1753
1754         if (becomeDisconnected && UNLIKELY(isDefinedCustomElement()))
1755             CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*this);
1756     }
1757
1758     if (!parentNode()) {
1759         if (auto* shadowRoot = insertionPoint.shadowRoot())
1760             shadowRoot->hostChildElementDidChange(*this);
1761     }
1762
1763     ContainerNode::removedFrom(insertionPoint);
1764
1765     if (hasPendingResources())
1766         document().accessSVGExtensions().removeElementFromPendingResources(this);
1767
1768     RefPtr<Frame> frame = document().frame();
1769     if (frame)
1770         frame->animation().cancelAnimations(*this);
1771
1772 #if PLATFORM(MAC)
1773     if (frame)
1774         frame->mainFrame().removeLatchingStateForTarget(*this);
1775 #endif
1776 }
1777
1778 ShadowRoot* Element::shadowRoot() const
1779 {
1780     return hasRareData() ? elementRareData()->shadowRoot() : nullptr;
1781 }
1782
1783 void Element::addShadowRoot(Ref<ShadowRoot>&& newShadowRoot)
1784 {
1785     ASSERT(!shadowRoot());
1786     
1787     if (renderer())
1788         RenderTreeUpdater::tearDownRenderers(*this);
1789
1790     ShadowRoot& shadowRoot = newShadowRoot;
1791     ensureElementRareData().setShadowRoot(WTFMove(newShadowRoot));
1792
1793     shadowRoot.setHost(this);
1794     shadowRoot.setParentTreeScope(treeScope());
1795
1796     NodeVector postInsertionNotificationTargets;
1797     notifyChildNodeInserted(*this, shadowRoot, postInsertionNotificationTargets);
1798     for (auto& target : postInsertionNotificationTargets)
1799         target->finishedInsertingSubtree();
1800
1801     invalidateStyleAndRenderersForSubtree();
1802
1803     InspectorInstrumentation::didPushShadowRoot(*this, shadowRoot);
1804
1805     if (shadowRoot.mode() == ShadowRootMode::UserAgent)
1806         didAddUserAgentShadowRoot(&shadowRoot);
1807 }
1808
1809 void Element::removeShadowRoot()
1810 {
1811     RefPtr<ShadowRoot> oldRoot = shadowRoot();
1812     if (!oldRoot)
1813         return;
1814
1815     InspectorInstrumentation::willPopShadowRoot(*this, *oldRoot);
1816     document().removeFocusedNodeOfSubtree(*oldRoot);
1817
1818     ASSERT(!oldRoot->renderer());
1819
1820     elementRareData()->clearShadowRoot();
1821
1822     oldRoot->setHost(nullptr);
1823     oldRoot->setParentTreeScope(document());
1824 }
1825
1826 static bool canAttachAuthorShadowRoot(const Element& element)
1827 {
1828     static NeverDestroyed<HashSet<AtomicString>> tagNames = [] {
1829         static const HTMLQualifiedName* const tagList[] = {
1830             &articleTag,
1831             &asideTag,
1832             &blockquoteTag,
1833             &bodyTag,
1834             &divTag,
1835             &footerTag,
1836             &h1Tag,
1837             &h2Tag,
1838             &h3Tag,
1839             &h4Tag,
1840             &h5Tag,
1841             &h6Tag,
1842             &headerTag,
1843             &navTag,
1844             &pTag,
1845             &sectionTag,
1846             &spanTag
1847         };
1848         HashSet<AtomicString> set;
1849         for (auto& name : tagList)
1850             set.add(name->localName());
1851         return set;
1852     }();
1853
1854     if (!is<HTMLElement>(element))
1855         return false;
1856
1857     const auto& localName = element.localName();
1858     return tagNames.get().contains(localName) || Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid;
1859 }
1860
1861 ExceptionOr<ShadowRoot&> Element::attachShadow(const ShadowRootInit& init)
1862 {
1863     if (!canAttachAuthorShadowRoot(*this))
1864         return Exception { NotSupportedError };
1865     if (shadowRoot())
1866         return Exception { InvalidStateError };
1867     if (init.mode == ShadowRootMode::UserAgent)
1868         return Exception { TypeError };
1869     auto shadow = ShadowRoot::create(document(), init.mode);
1870     auto& result = shadow.get();
1871     addShadowRoot(WTFMove(shadow));
1872     return result;
1873 }
1874
1875 ShadowRoot* Element::shadowRootForBindings(JSC::ExecState& state) const
1876 {
1877     auto* shadow = shadowRoot();
1878     if (!shadow)
1879         return nullptr;
1880     if (shadow->mode() == ShadowRootMode::Open)
1881         return shadow;
1882     if (JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())->world().shadowRootIsAlwaysOpen())
1883         return shadow;
1884     return nullptr;
1885 }
1886
1887 ShadowRoot* Element::userAgentShadowRoot() const
1888 {
1889     ASSERT(!shadowRoot() || shadowRoot()->mode() == ShadowRootMode::UserAgent);
1890     return shadowRoot();
1891 }
1892
1893 ShadowRoot& Element::ensureUserAgentShadowRoot()
1894 {
1895     if (auto* shadow = userAgentShadowRoot())
1896         return *shadow;
1897     auto newShadow = ShadowRoot::create(document(), ShadowRootMode::UserAgent);
1898     ShadowRoot& shadow = newShadow;
1899     addShadowRoot(WTFMove(newShadow));
1900     return shadow;
1901 }
1902
1903 void Element::setIsDefinedCustomElement(JSCustomElementInterface& elementInterface)
1904 {
1905     clearFlag(IsEditingTextOrUndefinedCustomElementFlag);
1906     setFlag(IsCustomElement);
1907     auto& data = ensureElementRareData();
1908     if (!data.customElementReactionQueue())
1909         data.setCustomElementReactionQueue(std::make_unique<CustomElementReactionQueue>(elementInterface));
1910     InspectorInstrumentation::didChangeCustomElementState(*this);
1911 }
1912
1913 void Element::setIsFailedCustomElement(JSCustomElementInterface&)
1914 {
1915     ASSERT(isUndefinedCustomElement());
1916     ASSERT(getFlag(IsEditingTextOrUndefinedCustomElementFlag));
1917     clearFlag(IsCustomElement);
1918
1919     if (hasRareData()) {
1920         // Clear the queue instead of deleting it since this function can be called inside CustomElementReactionQueue::invokeAll during upgrades.
1921         if (auto* queue = elementRareData()->customElementReactionQueue())
1922             queue->clear();
1923     }
1924     InspectorInstrumentation::didChangeCustomElementState(*this);
1925 }
1926
1927 void Element::setIsCustomElementUpgradeCandidate()
1928 {
1929     ASSERT(!getFlag(IsCustomElement));
1930     setFlag(IsCustomElement);
1931     setFlag(IsEditingTextOrUndefinedCustomElementFlag);
1932     InspectorInstrumentation::didChangeCustomElementState(*this);
1933 }
1934
1935 void Element::enqueueToUpgrade(JSCustomElementInterface& elementInterface)
1936 {
1937     ASSERT(!isDefinedCustomElement() && !isFailedCustomElement());
1938     setFlag(IsCustomElement);
1939     setFlag(IsEditingTextOrUndefinedCustomElementFlag);
1940     InspectorInstrumentation::didChangeCustomElementState(*this);
1941
1942     auto& data = ensureElementRareData();
1943     ASSERT(!data.customElementReactionQueue());
1944
1945     data.setCustomElementReactionQueue(std::make_unique<CustomElementReactionQueue>(elementInterface));
1946     data.customElementReactionQueue()->enqueueElementUpgrade(*this);
1947 }
1948
1949 CustomElementReactionQueue* Element::reactionQueue() const
1950 {
1951     ASSERT(isDefinedCustomElement() || isCustomElementUpgradeCandidate());
1952     if (!hasRareData())
1953         return nullptr;
1954     return elementRareData()->customElementReactionQueue();
1955 }
1956
1957 const AtomicString& Element::shadowPseudoId() const
1958 {
1959     return pseudo();
1960 }
1961
1962 bool Element::childTypeAllowed(NodeType type) const
1963 {
1964     switch (type) {
1965     case ELEMENT_NODE:
1966     case TEXT_NODE:
1967     case COMMENT_NODE:
1968     case PROCESSING_INSTRUCTION_NODE:
1969     case CDATA_SECTION_NODE:
1970         return true;
1971     default:
1972         break;
1973     }
1974     return false;
1975 }
1976
1977 static void checkForEmptyStyleChange(Element& element)
1978 {
1979     if (element.styleAffectedByEmpty()) {
1980         auto* style = element.renderStyle();
1981         if (!style || (!style->emptyState() || element.hasChildNodes()))
1982             element.invalidateStyleForSubtree();
1983     }
1984 }
1985
1986 enum SiblingCheckType { FinishedParsingChildren, SiblingElementRemoved, Other };
1987
1988 static void checkForSiblingStyleChanges(Element& parent, SiblingCheckType checkType, Element* elementBeforeChange, Element* elementAfterChange)
1989 {
1990     // :empty selector.
1991     checkForEmptyStyleChange(parent);
1992
1993     if (parent.styleValidity() >= Style::Validity::SubtreeInvalid)
1994         return;
1995
1996     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
1997     // In the DOM case, we only need to do something if |afterChange| is not 0.
1998     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
1999     if (parent.childrenAffectedByFirstChildRules() && elementAfterChange) {
2000         // Find our new first child.
2001         RefPtr<Element> newFirstElement = ElementTraversal::firstChild(parent);
2002         // Find the first element node following |afterChange|
2003
2004         // This is the insert/append case.
2005         if (newFirstElement != elementAfterChange) {
2006             auto* style = elementAfterChange->renderStyle();
2007             if (!style || style->firstChildState())
2008                 elementAfterChange->invalidateStyleForSubtree();
2009         }
2010
2011         // We also have to handle node removal.
2012         if (checkType == SiblingElementRemoved && newFirstElement == elementAfterChange && newFirstElement) {
2013             auto* style = newFirstElement->renderStyle();
2014             if (!style || !style->firstChildState())
2015                 newFirstElement->invalidateStyleForSubtree();
2016         }
2017     }
2018
2019     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
2020     // In the DOM case, we only need to do something if |afterChange| is not 0.
2021     if (parent.childrenAffectedByLastChildRules() && elementBeforeChange) {
2022         // Find our new last child.
2023         RefPtr<Element> newLastElement = ElementTraversal::lastChild(parent);
2024
2025         if (newLastElement != elementBeforeChange) {
2026             auto* style = elementBeforeChange->renderStyle();
2027             if (!style || style->lastChildState())
2028                 elementBeforeChange->invalidateStyleForSubtree();
2029         }
2030
2031         // 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
2032         // to match now.
2033         if ((checkType == SiblingElementRemoved || checkType == FinishedParsingChildren) && newLastElement == elementBeforeChange && newLastElement) {
2034             auto* style = newLastElement->renderStyle();
2035             if (!style || !style->lastChildState())
2036                 newLastElement->invalidateStyleForSubtree();
2037         }
2038     }
2039
2040     if (elementAfterChange) {
2041         if (elementAfterChange->styleIsAffectedByPreviousSibling())
2042             elementAfterChange->invalidateStyleForSubtree();
2043         else if (elementAfterChange->affectsNextSiblingElementStyle()) {
2044             Element* elementToInvalidate = elementAfterChange;
2045             do {
2046                 elementToInvalidate = elementToInvalidate->nextElementSibling();
2047             } while (elementToInvalidate && !elementToInvalidate->styleIsAffectedByPreviousSibling());
2048
2049             if (elementToInvalidate)
2050                 elementToInvalidate->invalidateStyleForSubtree();
2051         }
2052     }
2053
2054     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
2055     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
2056     // backward case.
2057     // |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.
2058     // 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
2059     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
2060     if (parent.childrenAffectedByBackwardPositionalRules() && elementBeforeChange)
2061         parent.invalidateStyleForSubtree();
2062 }
2063
2064 void Element::childrenChanged(const ChildChange& change)
2065 {
2066     ContainerNode::childrenChanged(change);
2067     if (change.source == ChildChangeSourceParser)
2068         checkForEmptyStyleChange(*this);
2069     else {
2070         SiblingCheckType checkType = change.type == ElementRemoved ? SiblingElementRemoved : Other;
2071         checkForSiblingStyleChanges(*this, checkType, change.previousSiblingElement, change.nextSiblingElement);
2072     }
2073
2074     if (ShadowRoot* shadowRoot = this->shadowRoot()) {
2075         switch (change.type) {
2076         case ElementInserted:
2077         case ElementRemoved:
2078             // For elements, we notify shadowRoot in Element::insertedInto and Element::removedFrom.
2079             break;
2080         case AllChildrenRemoved:
2081         case AllChildrenReplaced:
2082             shadowRoot->didRemoveAllChildrenOfShadowHost();
2083             break;
2084         case TextInserted:
2085         case TextRemoved:
2086         case TextChanged:
2087             shadowRoot->didChangeDefaultSlot();
2088             break;
2089         case NonContentsChildInserted:
2090         case NonContentsChildRemoved:
2091             break;
2092         }
2093     }
2094 }
2095
2096 void Element::setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& attributeValue)
2097 {
2098     setAttributeEventListener(eventType, JSLazyEventListener::create(*this, attributeName, attributeValue), mainThreadNormalWorld());
2099 }
2100
2101 void Element::removeAllEventListeners()
2102 {
2103     ContainerNode::removeAllEventListeners();
2104     if (ShadowRoot* shadowRoot = this->shadowRoot())
2105         shadowRoot->removeAllEventListeners();
2106 }
2107
2108 void Element::beginParsingChildren()
2109 {
2110     clearIsParsingChildrenFinished();
2111 }
2112
2113 void Element::finishParsingChildren()
2114 {
2115     ContainerNode::finishParsingChildren();
2116     setIsParsingChildrenFinished();
2117     checkForSiblingStyleChanges(*this, FinishedParsingChildren, ElementTraversal::lastChild(*this), nullptr);
2118 }
2119
2120 #if ENABLE(TREE_DEBUGGING)
2121 void Element::formatForDebugger(char* buffer, unsigned length) const
2122 {
2123     StringBuilder result;
2124     String s;
2125
2126     result.append(nodeName());
2127
2128     s = getIdAttribute();
2129     if (s.length() > 0) {
2130         if (result.length() > 0)
2131             result.appendLiteral("; ");
2132         result.appendLiteral("id=");
2133         result.append(s);
2134     }
2135
2136     s = getAttribute(classAttr);
2137     if (s.length() > 0) {
2138         if (result.length() > 0)
2139             result.appendLiteral("; ");
2140         result.appendLiteral("class=");
2141         result.append(s);
2142     }
2143
2144     strncpy(buffer, result.toString().utf8().data(), length - 1);
2145 }
2146 #endif
2147
2148 const Vector<RefPtr<Attr>>& Element::attrNodeList()
2149 {
2150     ASSERT(hasSyntheticAttrChildNodes());
2151     return *attrNodeListForElement(*this);
2152 }
2153
2154 void Element::attachAttributeNodeIfNeeded(Attr& attrNode)
2155 {
2156     ASSERT(!attrNode.ownerElement() || attrNode.ownerElement() == this);
2157     if (attrNode.ownerElement() == this)
2158         return;
2159
2160     NoEventDispatchAssertion assertNoEventDispatch;
2161
2162     attrNode.attachToElement(*this);
2163     ensureAttrNodeListForElement(*this).append(&attrNode);
2164 }
2165
2166 ExceptionOr<RefPtr<Attr>> Element::setAttributeNode(Attr& attrNode)
2167 {
2168     RefPtr<Attr> oldAttrNode = attrIfExists(attrNode.localName(), shouldIgnoreAttributeCase(*this));
2169     if (oldAttrNode.get() == &attrNode)
2170         return WTFMove(oldAttrNode);
2171
2172     // InUseAttributeError: Raised if node is an Attr that is already an attribute of another Element object.
2173     // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
2174     if (attrNode.ownerElement() && attrNode.ownerElement() != this)
2175         return Exception { InUseAttributeError };
2176
2177     {
2178     NoEventDispatchAssertion assertNoEventDispatch;
2179     synchronizeAllAttributes();
2180     }
2181
2182     auto& elementData = ensureUniqueElementData();
2183
2184     auto existingAttributeIndex = elementData.findAttributeIndexByName(attrNode.localName(), shouldIgnoreAttributeCase(*this));
2185
2186     // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value
2187     // before making changes to attrNode's Element connections.
2188     auto attrNodeValue = attrNode.value();
2189
2190     if (existingAttributeIndex == ElementData::attributeNotFound) {
2191         attachAttributeNodeIfNeeded(attrNode);
2192         setAttributeInternal(elementData.findAttributeIndexByName(attrNode.qualifiedName()), attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2193     } else {
2194         const Attribute& attribute = attributeAt(existingAttributeIndex);
2195         if (oldAttrNode)
2196             detachAttrNodeFromElementWithValue(oldAttrNode.get(), attribute.value());
2197         else
2198             oldAttrNode = Attr::create(document(), attrNode.qualifiedName(), attribute.value());
2199
2200         attachAttributeNodeIfNeeded(attrNode);
2201
2202         if (attribute.name().matches(attrNode.qualifiedName()))
2203             setAttributeInternal(existingAttributeIndex, attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2204         else {
2205             removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute);
2206             setAttributeInternal(ensureUniqueElementData().findAttributeIndexByName(attrNode.qualifiedName()), attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2207         }
2208     }
2209
2210     return WTFMove(oldAttrNode);
2211 }
2212
2213 ExceptionOr<RefPtr<Attr>> Element::setAttributeNodeNS(Attr& attrNode)
2214 {
2215     RefPtr<Attr> oldAttrNode = attrIfExists(attrNode.qualifiedName());
2216     if (oldAttrNode.get() == &attrNode)
2217         return WTFMove(oldAttrNode);
2218
2219     // InUseAttributeError: Raised if node is an Attr that is already an attribute of another Element object.
2220     // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
2221     if (attrNode.ownerElement() && attrNode.ownerElement() != this)
2222         return Exception { InUseAttributeError };
2223
2224     unsigned index = 0;
2225     
2226     // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value
2227     // before making changes to attrNode's Element connections.
2228     auto attrNodeValue = attrNode.value();
2229
2230     {
2231     NoEventDispatchAssertion assertNoEventDispatch;
2232     synchronizeAllAttributes();
2233     auto& elementData = ensureUniqueElementData();
2234
2235     index = elementData.findAttributeIndexByName(attrNode.qualifiedName());
2236
2237     if (index != ElementData::attributeNotFound) {
2238         if (oldAttrNode)
2239             detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData.attributeAt(index).value());
2240         else
2241             oldAttrNode = Attr::create(document(), attrNode.qualifiedName(), elementData.attributeAt(index).value());
2242     }
2243     }
2244
2245     attachAttributeNodeIfNeeded(attrNode);
2246     setAttributeInternal(index, attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
2247
2248     return WTFMove(oldAttrNode);
2249 }
2250
2251 ExceptionOr<Ref<Attr>> Element::removeAttributeNode(Attr& attr)
2252 {
2253     if (attr.ownerElement() != this)
2254         return Exception { NotFoundError };
2255
2256     ASSERT(&document() == &attr.document());
2257
2258     synchronizeAllAttributes();
2259
2260     if (!m_elementData)
2261         return Exception { NotFoundError };
2262
2263     auto existingAttributeIndex = m_elementData->findAttributeIndexByName(attr.qualifiedName());
2264     if (existingAttributeIndex == ElementData::attributeNotFound)
2265         return Exception { NotFoundError };
2266
2267     Ref<Attr> oldAttrNode { attr };
2268
2269     detachAttrNodeFromElementWithValue(&attr, m_elementData->attributeAt(existingAttributeIndex).value());
2270     removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute);
2271
2272     return WTFMove(oldAttrNode);
2273 }
2274
2275 ExceptionOr<QualifiedName> Element::parseAttributeName(const AtomicString& namespaceURI, const AtomicString& qualifiedName)
2276 {
2277     auto parseResult = Document::parseQualifiedName(namespaceURI, qualifiedName);
2278     if (parseResult.hasException())
2279         return parseResult.releaseException();
2280     QualifiedName parsedAttributeName { parseResult.releaseReturnValue() };
2281     if (!Document::hasValidNamespaceForAttributes(parsedAttributeName))
2282         return Exception { NamespaceError };
2283     return WTFMove(parsedAttributeName);
2284 }
2285
2286 ExceptionOr<void> Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value)
2287 {
2288     auto result = parseAttributeName(namespaceURI, qualifiedName);
2289     if (result.hasException())
2290         return result.releaseException();
2291     setAttribute(result.releaseReturnValue(), value);
2292     return { };
2293 }
2294
2295 void Element::removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
2296 {
2297     ASSERT_WITH_SECURITY_IMPLICATION(index < attributeCount());
2298
2299     UniqueElementData& elementData = ensureUniqueElementData();
2300
2301     QualifiedName name = elementData.attributeAt(index).name();
2302     AtomicString valueBeingRemoved = elementData.attributeAt(index).value();
2303
2304     if (RefPtr<Attr> attrNode = attrIfExists(name))
2305         detachAttrNodeFromElementWithValue(attrNode.get(), elementData.attributeAt(index).value());
2306
2307     if (inSynchronizationOfLazyAttribute) {
2308         elementData.removeAttribute(index);
2309         return;
2310     }
2311
2312     if (!valueBeingRemoved.isNull())
2313         willModifyAttribute(name, valueBeingRemoved, nullAtom());
2314
2315     {
2316         Style::AttributeChangeInvalidation styleInvalidation(*this, name, valueBeingRemoved, nullAtom());
2317         elementData.removeAttribute(index);
2318     }
2319
2320     didRemoveAttribute(name, valueBeingRemoved);
2321 }
2322
2323 void Element::addAttributeInternal(const QualifiedName& name, const AtomicString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
2324 {
2325     if (inSynchronizationOfLazyAttribute) {
2326         ensureUniqueElementData().addAttribute(name, value);
2327         return;
2328     }
2329
2330     willModifyAttribute(name, nullAtom(), value);
2331     {
2332         Style::AttributeChangeInvalidation styleInvalidation(*this, name, nullAtom(), value);
2333         ensureUniqueElementData().addAttribute(name, value);
2334     }
2335     didAddAttribute(name, value);
2336 }
2337
2338 bool Element::removeAttribute(const AtomicString& name)
2339 {
2340     if (!elementData())
2341         return false;
2342
2343     AtomicString localName = shouldIgnoreAttributeCase(*this) ? name.convertToASCIILowercase() : name;
2344     unsigned index = elementData()->findAttributeIndexByName(localName, false);
2345     if (index == ElementData::attributeNotFound) {
2346         if (UNLIKELY(localName == styleAttr) && elementData()->styleAttributeIsDirty() && is<StyledElement>(*this))
2347             downcast<StyledElement>(*this).removeAllInlineStyleProperties();
2348         return false;
2349     }
2350
2351     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
2352     return true;
2353 }
2354
2355 bool Element::removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName)
2356 {
2357     return removeAttribute(QualifiedName(nullAtom(), localName, namespaceURI));
2358 }
2359
2360 RefPtr<Attr> Element::getAttributeNode(const AtomicString& localName)
2361 {
2362     if (!elementData())
2363         return nullptr;
2364     synchronizeAttribute(localName);
2365     const Attribute* attribute = elementData()->findAttributeByName(localName, shouldIgnoreAttributeCase(*this));
2366     if (!attribute)
2367         return nullptr;
2368     return ensureAttr(attribute->name());
2369 }
2370
2371 RefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
2372 {
2373     if (!elementData())
2374         return 0;
2375     QualifiedName qName(nullAtom(), localName, namespaceURI);
2376     synchronizeAttribute(qName);
2377     const Attribute* attribute = elementData()->findAttributeByName(qName);
2378     if (!attribute)
2379         return 0;
2380     return ensureAttr(attribute->name());
2381 }
2382
2383 bool Element::hasAttribute(const AtomicString& localName) const
2384 {
2385     if (!elementData())
2386         return false;
2387     synchronizeAttribute(localName);
2388     return elementData()->findAttributeByName(localName, shouldIgnoreAttributeCase(*this));
2389 }
2390
2391 bool Element::hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const
2392 {
2393     if (!elementData())
2394         return false;
2395     QualifiedName qName(nullAtom(), localName, namespaceURI);
2396     synchronizeAttribute(qName);
2397     return elementData()->findAttributeByName(qName);
2398 }
2399
2400 void Element::focus(bool restorePreviousSelection, FocusDirection direction)
2401 {
2402     if (!isConnected())
2403         return;
2404
2405     if (document().focusedElement() == this) {
2406         if (document().page())
2407             document().page()->chrome().client().elementDidRefocus(*this);
2408
2409         return;
2410     }
2411
2412     // If the stylesheets have already been loaded we can reliably check isFocusable.
2413     // If not, we continue and set the focused node on the focus controller below so
2414     // that it can be updated soon after attach. 
2415     if (document().haveStylesheetsLoaded()) {
2416         document().updateLayoutIgnorePendingStylesheets();
2417         if (!isFocusable())
2418             return;
2419     }
2420
2421     if (!supportsFocus())
2422         return;
2423
2424     RefPtr<Node> protect;
2425     if (Page* page = document().page()) {
2426         // Focus and change event handlers can cause us to lose our last ref.
2427         // If a focus event handler changes the focus to a different node it
2428         // does not make sense to continue and update appearence.
2429         protect = this;
2430         if (!page->focusController().setFocusedElement(this, *document().frame(), direction))
2431             return;
2432     }
2433
2434     // Setting the focused node above might have invalidated the layout due to scripts.
2435     document().updateLayoutIgnorePendingStylesheets();
2436
2437     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
2438 #if PLATFORM(IOS)
2439     // Focusing a form element triggers animation in UIKit to scroll to the right position.
2440     // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(),
2441     // which would jump us around during this animation. See <rdar://problem/6699741>.
2442     bool isFormControl = is<HTMLFormControlElement>(*this);
2443     if (isFormControl)
2444         revealMode = SelectionRevealMode::RevealUpToMainFrame;
2445 #endif
2446
2447     updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault, revealMode);
2448 }
2449
2450 void Element::updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode revealMode)
2451 {
2452     if (isRootEditableElement()) {
2453         // Keep frame alive in this method, since setSelection() may release the last reference to |frame|.
2454         RefPtr<Frame> frame = document().frame();
2455         if (!frame)
2456             return;
2457         
2458         // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
2459         if (this == frame->selection().selection().rootEditableElement())
2460             return;
2461
2462         // FIXME: We should restore the previous selection if there is one.
2463         VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
2464         
2465         if (frame->selection().shouldChangeSelection(newSelection)) {
2466             frame->selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(), Element::defaultFocusTextStateChangeIntent());
2467             frame->selection().revealSelection(revealMode);
2468         }
2469     } else if (renderer() && !renderer()->isWidget()) {
2470         bool insideFixed;
2471         LayoutRect absoluteBounds = renderer()->absoluteAnchorRect(&insideFixed);
2472         renderer()->scrollRectToVisible(revealMode, absoluteBounds, insideFixed);
2473     }
2474 }
2475
2476 void Element::blur()
2477 {
2478     if (treeScope().focusedElementInScope() == this) {
2479         if (Frame* frame = document().frame())
2480             frame->page()->focusController().setFocusedElement(nullptr, *frame);
2481         else
2482             document().setFocusedElement(nullptr);
2483     }
2484 }
2485
2486 void Element::dispatchFocusInEvent(const AtomicString& eventType, RefPtr<Element>&& oldFocusedElement)
2487 {
2488     ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
2489     ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().DOMFocusInEvent);
2490     dispatchScopedEvent(FocusEvent::create(eventType, true, false, document().defaultView(), 0, WTFMove(oldFocusedElement)));
2491 }
2492
2493 void Element::dispatchFocusOutEvent(const AtomicString& eventType, RefPtr<Element>&& newFocusedElement)
2494 {
2495     ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
2496     ASSERT(eventType == eventNames().focusoutEvent || eventType == eventNames().DOMFocusOutEvent);
2497     dispatchScopedEvent(FocusEvent::create(eventType, true, false, document().defaultView(), 0, WTFMove(newFocusedElement)));
2498 }
2499
2500 void Element::dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection)
2501 {
2502     if (document().page())
2503         document().page()->chrome().client().elementDidFocus(*this);
2504
2505     EventDispatcher::dispatchEvent(*this, FocusEvent::create(eventNames().focusEvent, false, false, document().defaultView(), 0, WTFMove(oldFocusedElement)));
2506 }
2507
2508 void Element::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
2509 {
2510     if (document().page())
2511         document().page()->chrome().client().elementDidBlur(*this);
2512
2513     EventDispatcher::dispatchEvent(*this, FocusEvent::create(eventNames().blurEvent, false, false, document().defaultView(), 0, WTFMove(newFocusedElement)));
2514 }
2515
2516 void Element::dispatchWebKitImageReadyEventForTesting()
2517 {
2518     if (document().settings().webkitImageReadyEventEnabled())
2519         dispatchEvent(Event::create("webkitImageFrameReady", true, true));
2520 }
2521
2522 bool Element::dispatchMouseForceWillBegin()
2523 {
2524 #if ENABLE(MOUSE_FORCE_EVENTS)
2525     if (!document().hasListenerType(Document::FORCEWILLBEGIN_LISTENER))
2526         return false;
2527
2528     Frame* frame = document().frame();
2529     if (!frame)
2530         return false;
2531
2532     PlatformMouseEvent platformMouseEvent { frame->eventHandler().lastKnownMousePosition(), frame->eventHandler().lastKnownMouseGlobalPosition(), NoButton, PlatformEvent::NoType, 1, false, false, false, false, WallTime::now(), ForceAtClick, NoTap };
2533     auto mouseForceWillBeginEvent = MouseEvent::create(eventNames().webkitmouseforcewillbeginEvent, document().defaultView(), platformMouseEvent, 0, nullptr);
2534     mouseForceWillBeginEvent->setTarget(this);
2535     dispatchEvent(mouseForceWillBeginEvent);
2536
2537     if (mouseForceWillBeginEvent->defaultHandled() || mouseForceWillBeginEvent->defaultPrevented())
2538         return true;
2539 #endif
2540
2541     return false;
2542 }
2543
2544 ExceptionOr<void> Element::mergeWithNextTextNode(Text& node)
2545 {
2546     auto* next = node.nextSibling();
2547     if (!is<Text>(next))
2548         return { };
2549     Ref<Text> textNext { downcast<Text>(*next) };
2550     node.appendData(textNext->data());
2551     return textNext->remove();
2552 }
2553
2554 String Element::innerHTML() const
2555 {
2556     return createMarkup(*this, ChildrenOnly);
2557 }
2558
2559 String Element::outerHTML() const
2560 {
2561     return createMarkup(*this);
2562 }
2563
2564 ExceptionOr<void> Element::setOuterHTML(const String& html)
2565 {
2566     auto* parentElement = this->parentElement();
2567     if (!is<HTMLElement>(parentElement))
2568         return Exception { NoModificationAllowedError };
2569
2570     Ref<HTMLElement> parent = downcast<HTMLElement>(*parentElement);
2571     RefPtr<Node> prev = previousSibling();
2572     RefPtr<Node> next = nextSibling();
2573
2574     auto fragment = createFragmentForInnerOuterHTML(parent, html, AllowScriptingContent);
2575     if (fragment.hasException())
2576         return fragment.releaseException();
2577
2578     auto replaceResult = parent->replaceChild(fragment.releaseReturnValue().get(), *this);
2579     if (replaceResult.hasException())
2580         return replaceResult.releaseException();
2581
2582     RefPtr<Node> node = next ? next->previousSibling() : nullptr;
2583     if (is<Text>(node.get())) {
2584         auto result = mergeWithNextTextNode(downcast<Text>(*node));
2585         if (result.hasException())
2586             return result.releaseException();
2587     }
2588     if (is<Text>(prev.get())) {
2589         auto result = mergeWithNextTextNode(downcast<Text>(*prev));
2590         if (result.hasException())
2591             return result.releaseException();
2592     }
2593     return { };
2594 }
2595
2596
2597 ExceptionOr<void> Element::setInnerHTML(const String& html)
2598 {
2599     auto fragment = createFragmentForInnerOuterHTML(*this, html, AllowScriptingContent);
2600     if (fragment.hasException())
2601         return fragment.releaseException();
2602
2603     ContainerNode* container;
2604     if (!is<HTMLTemplateElement>(*this))
2605         container = this;
2606     else
2607         container = &downcast<HTMLTemplateElement>(*this).content();
2608
2609     return replaceChildrenWithFragment(*container, fragment.releaseReturnValue());
2610 }
2611
2612 String Element::innerText()
2613 {
2614     // We need to update layout, since plainText uses line boxes in the render tree.
2615     document().updateLayoutIgnorePendingStylesheets();
2616
2617     if (!renderer())
2618         return textContent(true);
2619
2620     return plainText(rangeOfContents(*this).ptr());
2621 }
2622
2623 String Element::outerText()
2624 {
2625     // Getting outerText is the same as getting innerText, only
2626     // setting is different. You would think this should get the plain
2627     // text for the outer range, but this is wrong, <br> for instance
2628     // would return different values for inner and outer text by such
2629     // a rule, but it doesn't in WinIE, and we want to match that.
2630     return innerText();
2631 }
2632
2633 String Element::title() const
2634 {
2635     return String();
2636 }
2637
2638 const AtomicString& Element::pseudo() const
2639 {
2640     return attributeWithoutSynchronization(pseudoAttr);
2641 }
2642
2643 void Element::setPseudo(const AtomicString& value)
2644 {
2645     setAttributeWithoutSynchronization(pseudoAttr, value);
2646 }
2647
2648 LayoutSize Element::minimumSizeForResizing() const
2649 {
2650     return hasRareData() ? elementRareData()->minimumSizeForResizing() : defaultMinimumSizeForResizing();
2651 }
2652
2653 void Element::setMinimumSizeForResizing(const LayoutSize& size)
2654 {
2655     if (!hasRareData() && size == defaultMinimumSizeForResizing())
2656         return;
2657     ensureElementRareData().setMinimumSizeForResizing(size);
2658 }
2659
2660 void Element::willBecomeFullscreenElement()
2661 {
2662     for (auto& child : descendantsOfType<Element>(*this))
2663         child.ancestorWillEnterFullscreen();
2664 }
2665
2666 static PseudoElement* beforeOrAfterPseudoElement(Element& host, PseudoId pseudoElementSpecifier)
2667 {
2668     switch (pseudoElementSpecifier) {
2669     case BEFORE:
2670         return host.beforePseudoElement();
2671     case AFTER:
2672         return host.afterPseudoElement();
2673     default:
2674         return nullptr;
2675     }
2676 }
2677
2678 const RenderStyle* Element::existingComputedStyle() const
2679 {
2680     if (auto* renderTreeStyle = renderStyle())
2681         return renderTreeStyle;
2682
2683     if (hasRareData())
2684         return elementRareData()->computedStyle();
2685
2686     return nullptr;
2687 }
2688
2689 const RenderStyle& Element::resolveComputedStyle()
2690 {
2691     ASSERT(isConnected());
2692     ASSERT(!existingComputedStyle());
2693
2694     Deque<Element*, 32> elementsRequiringComputedStyle({ this });
2695     const RenderStyle* computedStyle = nullptr;
2696
2697     // Collect ancestors until we find one that has style.
2698     auto composedAncestors = composedTreeAncestors(*this);
2699     for (auto& ancestor : composedAncestors) {
2700         if (auto* existingStyle = ancestor.existingComputedStyle()) {
2701             computedStyle = existingStyle;
2702             break;
2703         }
2704         elementsRequiringComputedStyle.prepend(&ancestor);
2705     }
2706
2707     // Resolve and cache styles starting from the most distant ancestor.
2708     for (auto* element : elementsRequiringComputedStyle) {
2709         auto style = document().styleForElementIgnoringPendingStylesheets(*element, computedStyle);
2710         computedStyle = style.get();
2711         ElementRareData& rareData = element->ensureElementRareData();
2712         rareData.setComputedStyle(WTFMove(style));
2713     }
2714
2715     return *computedStyle;
2716 }
2717
2718 const RenderStyle& Element::resolvePseudoElementStyle(PseudoId pseudoElementSpecifier)
2719 {
2720     ASSERT(!isPseudoElement());
2721
2722     auto* parentStyle = existingComputedStyle();
2723     ASSERT(parentStyle);
2724     ASSERT(!parentStyle->getCachedPseudoStyle(pseudoElementSpecifier));
2725
2726     auto style = document().styleForElementIgnoringPendingStylesheets(*this, parentStyle, pseudoElementSpecifier);
2727     if (!style) {
2728         style = RenderStyle::createPtr();
2729         style->inheritFrom(*parentStyle);
2730         style->setStyleType(pseudoElementSpecifier);
2731     }
2732
2733     auto* computedStyle = style.get();
2734     const_cast<RenderStyle*>(parentStyle)->addCachedPseudoStyle(WTFMove(style));
2735     return *computedStyle;
2736 }
2737
2738 const RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
2739 {
2740     if (!isConnected())
2741         return nullptr;
2742
2743     if (PseudoElement* pseudoElement = beforeOrAfterPseudoElement(*this, pseudoElementSpecifier))
2744         return pseudoElement->computedStyle();
2745
2746     auto* style = existingComputedStyle();
2747     if (!style)
2748         style = &resolveComputedStyle();
2749
2750     if (pseudoElementSpecifier) {
2751         if (auto* cachedPseudoStyle = style->getCachedPseudoStyle(pseudoElementSpecifier))
2752             return cachedPseudoStyle;
2753         return &resolvePseudoElementStyle(pseudoElementSpecifier);
2754     }
2755
2756     return style;
2757 }
2758
2759 bool Element::needsStyleInvalidation() const
2760 {
2761     if (!inRenderedDocument())
2762         return false;
2763     if (styleValidity() >= Style::Validity::SubtreeInvalid)
2764         return false;
2765     if (document().hasPendingForcedStyleRecalc())
2766         return false;
2767
2768     return true;
2769 }
2770
2771 void Element::setStyleAffectedByEmpty()
2772 {
2773     ensureElementRareData().setStyleAffectedByEmpty(true);
2774 }
2775
2776 void Element::setStyleAffectedByFocusWithin()
2777 {
2778     ensureElementRareData().setStyleAffectedByFocusWithin(true);
2779 }
2780
2781 void Element::setStyleAffectedByActive()
2782 {
2783     ensureElementRareData().setStyleAffectedByActive(true);
2784 }
2785
2786 void Element::setChildrenAffectedByDrag()
2787 {
2788     ensureElementRareData().setChildrenAffectedByDrag(true);
2789 }
2790
2791 void Element::setChildrenAffectedByBackwardPositionalRules()
2792 {
2793     ensureElementRareData().setChildrenAffectedByBackwardPositionalRules(true);
2794 }
2795
2796 void Element::setChildrenAffectedByPropertyBasedBackwardPositionalRules()
2797 {
2798     ensureElementRareData().setChildrenAffectedByPropertyBasedBackwardPositionalRules(true);
2799 }
2800
2801 void Element::setChildIndex(unsigned index)
2802 {
2803     ElementRareData& rareData = ensureElementRareData();
2804     rareData.setChildIndex(index);
2805 }
2806
2807 bool Element::hasFlagsSetDuringStylingOfChildren() const
2808 {
2809     if (childrenAffectedByHover() || childrenAffectedByFirstChildRules() || childrenAffectedByLastChildRules())
2810         return true;
2811
2812     if (!hasRareData())
2813         return false;
2814     return rareDataStyleAffectedByActive()
2815         || rareDataChildrenAffectedByDrag()
2816         || rareDataChildrenAffectedByBackwardPositionalRules()
2817         || rareDataChildrenAffectedByPropertyBasedBackwardPositionalRules();
2818 }
2819
2820 bool Element::rareDataStyleAffectedByEmpty() const
2821 {
2822     ASSERT(hasRareData());
2823     return elementRareData()->styleAffectedByEmpty();
2824 }
2825
2826 bool Element::rareDataStyleAffectedByFocusWithin() const
2827 {
2828     ASSERT(hasRareData());
2829     return elementRareData()->styleAffectedByFocusWithin();
2830 }
2831
2832 bool Element::rareDataStyleAffectedByActive() const
2833 {
2834     ASSERT(hasRareData());
2835     return elementRareData()->styleAffectedByActive();
2836 }
2837
2838 bool Element::rareDataChildrenAffectedByDrag() const
2839 {
2840     ASSERT(hasRareData());
2841     return elementRareData()->childrenAffectedByDrag();
2842 }
2843
2844 bool Element::rareDataChildrenAffectedByBackwardPositionalRules() const
2845 {
2846     ASSERT(hasRareData());
2847     return elementRareData()->childrenAffectedByBackwardPositionalRules();
2848 }
2849
2850 bool Element::rareDataChildrenAffectedByPropertyBasedBackwardPositionalRules() const
2851 {
2852     ASSERT(hasRareData());
2853     return elementRareData()->childrenAffectedByPropertyBasedBackwardPositionalRules();
2854 }
2855
2856 unsigned Element::rareDataChildIndex() const
2857 {
2858     ASSERT(hasRareData());
2859     return elementRareData()->childIndex();
2860 }
2861
2862 AtomicString Element::computeInheritedLanguage() const
2863 {
2864     if (const ElementData* elementData = this->elementData()) {
2865         if (const Attribute* attribute = elementData->findLanguageAttribute())
2866             return attribute->value();
2867     }
2868
2869     // The language property is inherited, so we iterate over the parents to find the first language.
2870     const Node* currentNode = this;
2871     while ((currentNode = currentNode->parentNode())) {
2872         if (is<Element>(*currentNode)) {
2873             if (const ElementData* elementData = downcast<Element>(*currentNode).elementData()) {
2874                 if (const Attribute* attribute = elementData->findLanguageAttribute())
2875                     return attribute->value();
2876             }
2877         } else if (is<Document>(*currentNode)) {
2878             // checking the MIME content-language
2879             return downcast<Document>(*currentNode).contentLanguage();
2880         }
2881     }
2882
2883     return nullAtom();
2884 }
2885
2886 Locale& Element::locale() const
2887 {
2888     return document().getCachedLocale(computeInheritedLanguage());
2889 }
2890
2891 void Element::normalizeAttributes()
2892 {
2893     if (!hasAttributes())
2894         return;
2895
2896     auto* attrNodeList = attrNodeListForElement(*this);
2897     if (!attrNodeList)
2898         return;
2899
2900     // Copy the Attr Vector because Node::normalize() can fire synchronous JS
2901     // events (e.g. DOMSubtreeModified) and a JS listener could add / remove
2902     // attributes while we are iterating.
2903     auto copyOfAttrNodeList = *attrNodeList;
2904     for (auto& attrNode : copyOfAttrNodeList)
2905         attrNode->normalize();
2906 }
2907
2908 PseudoElement* Element::beforePseudoElement() const
2909 {
2910     return hasRareData() ? elementRareData()->beforePseudoElement() : nullptr;
2911 }
2912
2913 PseudoElement* Element::afterPseudoElement() const
2914 {
2915     return hasRareData() ? elementRareData()->afterPseudoElement() : nullptr;
2916 }
2917
2918 void Element::setBeforePseudoElement(Ref<PseudoElement>&& element)
2919 {
2920     ensureElementRareData().setBeforePseudoElement(WTFMove(element));
2921 }
2922
2923 void Element::setAfterPseudoElement(Ref<PseudoElement>&& element)
2924 {
2925     ensureElementRareData().setAfterPseudoElement(WTFMove(element));
2926 }
2927
2928 static void disconnectPseudoElement(PseudoElement* pseudoElement)
2929 {
2930     if (!pseudoElement)
2931         return;
2932     if (pseudoElement->renderer())
2933         RenderTreeUpdater::tearDownRenderers(*pseudoElement);
2934     ASSERT(pseudoElement->hostElement());
2935     pseudoElement->clearHostElement();
2936 }
2937
2938 void Element::clearBeforePseudoElement()
2939 {
2940     if (!hasRareData())
2941         return;
2942     disconnectPseudoElement(elementRareData()->beforePseudoElement());
2943     elementRareData()->setBeforePseudoElement(nullptr);
2944 }
2945
2946 void Element::clearAfterPseudoElement()
2947 {
2948     if (!hasRareData())
2949         return;
2950     disconnectPseudoElement(elementRareData()->afterPseudoElement());
2951     elementRareData()->setAfterPseudoElement(nullptr);
2952 }
2953
2954 bool Element::matchesValidPseudoClass() const
2955 {
2956     return false;
2957 }
2958
2959 bool Element::matchesInvalidPseudoClass() const
2960 {
2961     return false;
2962 }
2963
2964 bool Element::matchesReadWritePseudoClass() const
2965 {
2966     return false;
2967 }
2968
2969 bool Element::matchesIndeterminatePseudoClass() const
2970 {
2971     return shouldAppearIndeterminate();
2972 }
2973
2974 bool Element::matchesDefaultPseudoClass() const
2975 {
2976     return false;
2977 }
2978
2979 ExceptionOr<bool> Element::matches(const String& selector)
2980 {
2981     auto query = document().selectorQueryForString(selector);
2982     if (query.hasException())
2983         return query.releaseException();
2984     return query.releaseReturnValue().matches(*this);
2985 }
2986
2987 ExceptionOr<Element*> Element::closest(const String& selector)
2988 {
2989     auto query = document().selectorQueryForString(selector);
2990     if (query.hasException())
2991         return query.releaseException();
2992     return query.releaseReturnValue().closest(*this);
2993 }
2994
2995 bool Element::shouldAppearIndeterminate() const
2996 {
2997     return false;
2998 }
2999
3000 bool Element::mayCauseRepaintInsideViewport(const IntRect* visibleRect) const
3001 {
3002     return renderer() && renderer()->mayCauseRepaintInsideViewport(visibleRect);
3003 }
3004
3005 DOMTokenList& Element::classList()
3006 {
3007     ElementRareData& data = ensureElementRareData();
3008     if (!data.classList())
3009         data.setClassList(std::make_unique<DOMTokenList>(*this, HTMLNames::classAttr));
3010     return *data.classList();
3011 }
3012
3013 DatasetDOMStringMap& Element::dataset()
3014 {
3015     ElementRareData& data = ensureElementRareData();
3016     if (!data.dataset())
3017         data.setDataset(std::make_unique<DatasetDOMStringMap>(*this));
3018     return *data.dataset();
3019 }
3020
3021 URL Element::getURLAttribute(const QualifiedName& name) const
3022 {
3023 #if !ASSERT_DISABLED
3024     if (elementData()) {
3025         if (const Attribute* attribute = findAttributeByName(name))
3026             ASSERT(isURLAttribute(*attribute));
3027     }
3028 #endif
3029     return document().completeURL(stripLeadingAndTrailingHTMLSpaces(getAttribute(name)));
3030 }
3031
3032 URL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
3033 {
3034 #if !ASSERT_DISABLED
3035     if (elementData()) {
3036         if (const Attribute* attribute = findAttributeByName(name))
3037             ASSERT(isURLAttribute(*attribute));
3038     }
3039 #endif
3040     String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
3041     if (value.isEmpty())
3042         return URL();
3043     return document().completeURL(value);
3044 }
3045
3046 int Element::getIntegralAttribute(const QualifiedName& attributeName) const
3047 {
3048     return parseHTMLInteger(getAttribute(attributeName)).valueOr(0);
3049 }
3050
3051 void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
3052 {
3053     setAttribute(attributeName, AtomicString::number(value));
3054 }
3055
3056 unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
3057 {
3058     return parseHTMLNonNegativeInteger(getAttribute(attributeName)).valueOr(0);
3059 }
3060
3061 void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
3062 {
3063     setAttribute(attributeName, AtomicString::number(limitToOnlyHTMLNonNegative(value)));
3064 }
3065
3066 bool Element::childShouldCreateRenderer(const Node& child) const
3067 {
3068     // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
3069     if (child.isSVGElement()) {
3070         ASSERT(!isSVGElement());
3071         const SVGElement& childElement = downcast<SVGElement>(child);
3072         return is<SVGSVGElement>(childElement) && childElement.isValid();
3073     }
3074     return true;
3075 }
3076
3077 #if ENABLE(FULLSCREEN_API)
3078 void Element::webkitRequestFullscreen()
3079 {
3080     document().requestFullScreenForElement(this, Document::EnforceIFrameAllowFullScreenRequirement);
3081 }
3082
3083 bool Element::containsFullScreenElement() const
3084 {
3085     return hasRareData() && elementRareData()->containsFullScreenElement();
3086 }
3087
3088 void Element::setContainsFullScreenElement(bool flag)
3089 {
3090     ensureElementRareData().setContainsFullScreenElement(flag);
3091     invalidateStyleAndLayerComposition();
3092 }
3093
3094 static Element* parentCrossingFrameBoundaries(Element* element)
3095 {
3096     ASSERT(element);
3097     return element->parentElement() ? element->parentElement() : element->document().ownerElement();
3098 }
3099
3100 void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
3101 {
3102     Element* element = this;
3103     while ((element = parentCrossingFrameBoundaries(element)))
3104         element->setContainsFullScreenElement(flag);
3105 }
3106 #endif
3107
3108 #if ENABLE(POINTER_LOCK)
3109 void Element::requestPointerLock()
3110 {
3111     if (document().page())
3112         document().page()->pointerLockController().requestPointerLock(this);
3113 }
3114 #endif
3115
3116 SpellcheckAttributeState Element::spellcheckAttributeState() const
3117 {
3118     const AtomicString& value = attributeWithoutSynchronization(HTMLNames::spellcheckAttr);
3119     if (value.isNull())
3120         return SpellcheckAttributeDefault;
3121     if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "true"))
3122         return SpellcheckAttributeTrue;
3123     if (equalLettersIgnoringASCIICase(value, "false"))
3124         return SpellcheckAttributeFalse;
3125     return SpellcheckAttributeDefault;
3126 }
3127
3128 bool Element::isSpellCheckingEnabled() const
3129 {
3130     for (const Element* element = this; element; element = element->parentOrShadowHostElement()) {
3131         switch (element->spellcheckAttributeState()) {
3132         case SpellcheckAttributeTrue:
3133             return true;
3134         case SpellcheckAttributeFalse:
3135             return false;
3136         case SpellcheckAttributeDefault:
3137             break;
3138         }
3139     }
3140
3141     return true;
3142 }
3143
3144 #ifndef NDEBUG
3145 bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
3146 {
3147     if (name == HTMLNames::styleAttr)
3148         return false;
3149
3150     if (isSVGElement())
3151         return !downcast<SVGElement>(*this).isAnimatableAttribute(name);
3152
3153     return true;
3154 }
3155 #endif
3156
3157 #ifdef DUMP_NODE_STATISTICS
3158 bool Element::hasNamedNodeMap() const
3159 {
3160     return hasRareData() && elementRareData()->attributeMap();
3161 }
3162 #endif
3163
3164 inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
3165 {
3166     if (!isInTreeScope())
3167         return;
3168
3169     if (oldName == newName)
3170         return;
3171
3172     updateNameForTreeScope(treeScope(), oldName, newName);
3173
3174     if (!isConnected())
3175         return;
3176     if (!is<HTMLDocument>(document()))
3177         return;
3178     updateNameForDocument(downcast<HTMLDocument>(document()), oldName, newName);
3179 }
3180
3181 void Element::updateNameForTreeScope(TreeScope& scope, const AtomicString& oldName, const AtomicString& newName)
3182 {
3183     ASSERT(oldName != newName);
3184
3185     if (!oldName.isEmpty())
3186         scope.removeElementByName(*oldName.impl(), *this);
3187     if (!newName.isEmpty())
3188         scope.addElementByName(*newName.impl(), *this);
3189 }
3190
3191 void Element::updateNameForDocument(HTMLDocument& document, const AtomicString& oldName, const AtomicString& newName)
3192 {
3193     ASSERT(oldName != newName);
3194
3195     if (isInShadowTree())
3196         return;
3197
3198     if (WindowNameCollection::elementMatchesIfNameAttributeMatch(*this)) {
3199         const AtomicString& id = WindowNameCollection::elementMatchesIfIdAttributeMatch(*this) ? getIdAttribute() : nullAtom();
3200         if (!oldName.isEmpty() && oldName != id)
3201             document.removeWindowNamedItem(*oldName.impl(), *this);
3202         if (!newName.isEmpty() && newName != id)
3203             document.addWindowNamedItem(*newName.impl(), *this);
3204     }
3205
3206     if (DocumentNameCollection::elementMatchesIfNameAttributeMatch(*this)) {
3207         const AtomicString& id = DocumentNameCollection::elementMatchesIfIdAttributeMatch(*this) ? getIdAttribute() : nullAtom();
3208         if (!oldName.isEmpty() && oldName != id)
3209             document.removeDocumentNamedItem(*oldName.impl(), *this);
3210         if (!newName.isEmpty() && newName != id)
3211             document.addDocumentNamedItem(*newName.impl(), *this);
3212     }
3213 }
3214
3215 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId, NotifyObservers notifyObservers)
3216 {
3217     if (!isInTreeScope())
3218         return;
3219
3220     if (oldId == newId)
3221         return;
3222
3223     updateIdForTreeScope(treeScope(), oldId, newId, notifyObservers);
3224
3225     if (!isConnected())
3226         return;
3227     if (!is<HTMLDocument>(document()))
3228         return;
3229     updateIdForDocument(downcast<HTMLDocument>(document()), oldId, newId, UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute);
3230 }
3231
3232 void Element::updateIdForTreeScope(TreeScope& scope, const AtomicString& oldId, const AtomicString& newId, NotifyObservers notifyObservers)
3233 {
3234     ASSERT(isInTreeScope());
3235     ASSERT(oldId != newId);
3236
3237     if (!oldId.isEmpty())
3238         scope.removeElementById(*oldId.impl(), *this, notifyObservers == NotifyObservers::Yes);
3239     if (!newId.isEmpty())
3240         scope.addElementById(*newId.impl(), *this, notifyObservers == NotifyObservers::Yes);
3241 }
3242
3243 void Element::updateIdForDocument(HTMLDocument& document, const AtomicString& oldId, const AtomicString& newId, HTMLDocumentNamedItemMapsUpdatingCondition condition)
3244 {
3245     ASSERT(isConnected());
3246     ASSERT(oldId != newId);
3247
3248     if (isInShadowTree())
3249         return;
3250
3251     if (WindowNameCollection::elementMatchesIfIdAttributeMatch(*this)) {
3252         const AtomicString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && WindowNameCollection::elementMatchesIfNameAttributeMatch(*this) ? getNameAttribute() : nullAtom();
3253         if (!oldId.isEmpty() && oldId != name)
3254             document.removeWindowNamedItem(*oldId.impl(), *this);
3255         if (!newId.isEmpty() && newId != name)
3256             document.addWindowNamedItem(*newId.impl(), *this);
3257     }
3258
3259     if (DocumentNameCollection::elementMatchesIfIdAttributeMatch(*this)) {
3260         const AtomicString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && DocumentNameCollection::elementMatchesIfNameAttributeMatch(*this) ? getNameAttribute() : nullAtom();
3261         if (!oldId.isEmpty() && oldId != name)
3262             document.removeDocumentNamedItem(*oldId.impl(), *this);
3263         if (!newId.isEmpty() && newId != name)
3264             document.addDocumentNamedItem(*newId.impl(), *this);
3265     }
3266 }
3267
3268 void Element::updateLabel(TreeScope& scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
3269 {
3270     ASSERT(hasTagName(labelTag));
3271
3272     if (!isConnected())
3273         return;
3274
3275     if (oldForAttributeValue == newForAttributeValue)
3276         return;
3277
3278     if (!oldForAttributeValue.isEmpty())
3279         scope.removeLabel(*oldForAttributeValue.impl(), downcast<HTMLLabelElement>(*this));
3280     if (!newForAttributeValue.isEmpty())
3281         scope.addLabel(*newForAttributeValue.impl(), downcast<HTMLLabelElement>(*this));
3282 }
3283
3284 void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
3285 {
3286     if (name == HTMLNames::idAttr)
3287         updateId(oldValue, newValue, NotifyObservers::No); // Will notify observers after the attribute is actually changed.
3288     else if (name == HTMLNames::nameAttr)
3289         updateName(oldValue, newValue);
3290     else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
3291         if (treeScope().shouldCacheLabelsByForAttribute())
3292             updateLabel(treeScope(), oldValue, newValue);
3293     }
3294
3295     if (auto recipients = MutationObserverInterestGroup::createForAttributesMutation(*this, name))
3296         recipients->enqueueMutationRecord(MutationRecord::createAttributes(*this, name, oldValue));
3297
3298     InspectorInstrumentation::willModifyDOMAttr(document(), *this, oldValue, newValue);
3299 }
3300
3301 void Element::didAddAttribute(const QualifiedName& name, const AtomicString& value)
3302 {
3303     attributeChanged(name, nullAtom(), value);
3304     InspectorInstrumentation::didModifyDOMAttr(document(), *this, name.localName(), value);
3305     dispatchSubtreeModifiedEvent();
3306 }
3307
3308 void Element::didModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
3309 {
3310     attributeChanged(name, oldValue, newValue);
3311     InspectorInstrumentation::didModifyDOMAttr(document(), *this, name.localName(), newValue);
3312     // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
3313 }
3314
3315 void Element::didRemoveAttribute(const QualifiedName& name, const AtomicString& oldValue)
3316 {
3317     attributeChanged(name, oldValue, nullAtom());
3318     InspectorInstrumentation::didRemoveDOMAttr(document(), *this, name.localName());
3319     dispatchSubtreeModifiedEvent();
3320 }
3321
3322 IntPoint Element::savedLayerScrollPosition() const
3323 {
3324     return hasRareData() ? elementRareData()->savedLayerScrollPosition() : IntPoint();
3325 }
3326
3327 void Element::setSavedLayerScrollPosition(const IntPoint& position)
3328 {
3329     if (position.isZero() && !hasRareData())
3330         return;
3331     ensureElementRareData().setSavedLayerScrollPosition(position);
3332 }
3333
3334 RefPtr<Attr> Element::attrIfExists(const AtomicString& localName, bool shouldIgnoreAttributeCase)
3335 {
3336     if (auto* attrNodeList = attrNodeListForElement(*this))
3337         return findAttrNodeInList(*attrNodeList, localName, shouldIgnoreAttributeCase);
3338     return nullptr;
3339 }
3340
3341 RefPtr<Attr> Element::attrIfExists(const QualifiedName& name)
3342 {
3343     if (auto* attrNodeList = attrNodeListForElement(*this))
3344         return findAttrNodeInList(*attrNodeList, name);
3345     return nullptr;
3346 }
3347
3348 Ref<Attr> Element::ensureAttr(const QualifiedName& name)
3349 {
3350     auto& attrNodeList = ensureAttrNodeListForElement(*this);
3351     RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, name);
3352     if (!attrNode) {
3353         attrNode = Attr::create(*this, name);
3354         attrNode->setTreeScopeRecursively(treeScope());
3355         attrNodeList.append(attrNode);
3356     }
3357     return attrNode.releaseNonNull();
3358 }
3359
3360 void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomicString& value)
3361 {
3362     ASSERT(hasSyntheticAttrChildNodes());
3363     attrNode->detachFromElementWithValue(value);
3364
3365     auto& attrNodeList = *attrNodeListForElement(*this);
3366     bool found = attrNodeList.removeFirstMatching([attrNode](auto& attribute) {
3367         return attribute->qualifiedName() == attrNode->qualifiedName();
3368     });
3369     ASSERT_UNUSED(found, found);
3370     if (attrNodeList.isEmpty())
3371         removeAttrNodeListForElement(*this);
3372 }
3373
3374 void Element::detachAllAttrNodesFromElement()
3375 {
3376     auto* attrNodeList = attrNodeListForElement(*this);
3377     ASSERT(attrNodeList);
3378
3379     for (const Attribute& attribute : attributesIterator()) {
3380         if (RefPtr<Attr> attrNode = findAttrNodeInList(*attrNodeList, attribute.name()))
3381             attrNode->detachFromElementWithValue(attribute.value());
3382     }
3383
3384     removeAttrNodeListForElement(*this);
3385 }
3386
3387 void Element::resetComputedStyle()
3388 {
3389     if (!hasRareData() || !elementRareData()->computedStyle())
3390         return;
3391
3392     auto reset = [](Element& element) {
3393         if (!element.hasRareData() || !element.elementRareData()->computedStyle())
3394             return;
3395         if (element.hasCustomStyleResolveCallbacks())
3396             element.willResetComputedStyle();
3397         element.elementRareData()->resetComputedStyle();
3398     };
3399     reset(*this);
3400     for (auto& child : descendantsOfType<Element>(*this))
3401         reset(child);
3402 }
3403
3404 void Element::resetStyleRelations()
3405 {
3406     if (!hasRareData())
3407         return;
3408     elementRareData()->resetStyleRelations();
3409 }
3410
3411 void Element::clearStyleDerivedDataBeforeDetachingRenderer()
3412 {
3413     clearBeforePseudoElement();
3414     clearAfterPseudoElement();
3415 }
3416
3417 void Element::clearHoverAndActiveStatusBeforeDetachingRenderer()
3418 {
3419     if (!isUserActionElement())
3420         return;
3421     if (hovered())
3422         document().hoveredElementDidDetach(this);
3423     if (inActiveChain())
3424         document().elementInActiveChainDidDetach(this);
3425     document().userActionElements().didDetach(this);
3426 }
3427
3428 void Element::willRecalcStyle(Style::Change)
3429 {
3430     ASSERT(hasCustomStyleResolveCallbacks());
3431 }
3432
3433 void Element::didRecalcStyle(Style::Change)
3434 {
3435     ASSERT(hasCustomStyleResolveCallbacks());
3436 }
3437
3438 void Element::willResetComputedStyle()
3439 {
3440     ASSERT(hasCustomStyleResolveCallbacks());
3441 }
3442
3443 void Element::willAttachRenderers()
3444 {
3445     ASSERT(hasCustomStyleResolveCallbacks());
3446 }
3447
3448 void Element::didAttachRenderers()
3449 {
3450     ASSERT(hasCustomStyleResolveCallbacks());
3451 }
3452
3453 void Element::willDetachRenderers()
3454 {
3455     ASSERT(hasCustomStyleResolveCallbacks());
3456 }
3457
3458 void Element::didDetachRenderers()
3459 {
3460     ASSERT(hasCustomStyleResolveCallbacks());
3461 }
3462
3463 std::optional<ElementStyle> Element::resolveCustomStyle(const RenderStyle&, const RenderStyle*)
3464 {
3465     ASSERT(hasCustomStyleResolveCallbacks());
3466     return std::nullopt;
3467 }
3468
3469 void Element::cloneAttributesFromElement(const Element& other)
3470 {
3471     if (hasSyntheticAttrChildNodes())
3472         detachAllAttrNodesFromElement();
3473
3474     other.synchronizeAllAttributes();
3475     if (!other.m_elementData) {
3476         m_elementData = nullptr;
3477         return;
3478     }
3479
3480     // 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.
3481     // Fortunately, those named item maps are only updated when this element is in the document, which should never be the case.
3482     ASSERT(!isConnected());
3483
3484     const AtomicString& oldID = getIdAttribute();
3485     const AtomicString& newID = other.getIdAttribute();
3486
3487     if (!oldID.isNull() || !newID.isNull())
3488         updateId(oldID, newID, NotifyObservers::No); // Will notify observers after the attribute is actually changed.
3489
3490     const AtomicString& oldName = getNameAttribute();
3491     const AtomicString& newName = other.getNameAttribute();
3492
3493     if (!oldName.isNull() || !newName.isNull())
3494         updateName(oldName, newName);
3495
3496     // If 'other' has a mutable ElementData, convert it to an immutable one so we can share it between both elements.
3497     // We can only do this if there is no CSSOM wrapper for other's inline style, and there are no presentation attributes.
3498     if (is<UniqueElementData>(*other.m_elementData)
3499         && !other.m_elementData->presentationAttributeStyle()
3500         && (!other.m_elementData->inlineStyle() || !other.m_elementData->inlineStyle()->hasCSSOMWrapper()))
3501         const_cast<Element&>(other).m_elementData = downcast<UniqueElementData>(*other.m_elementData).makeShareableCopy();
3502
3503     if (!other.m_elementData->isUnique())
3504         m_elementData = other.m_elementData;
3505     else
3506         m_elementData = other.m_elementData->makeUniqueCopy();
3507
3508     for (const Attribute& attribute : attributesIterator())
3509         attributeChanged(attribute.name(), nullAtom(), attribute.value(), ModifiedByCloning);
3510 }
3511
3512 void Element::cloneDataFromElement(const Element& other)
3513 {
3514     cloneAttributesFromElement(other);
3515     copyNonAttributePropertiesFromElement(other);
3516 }
3517
3518 void Element::createUniqueElementData()
3519 {
3520     if (!m_elementData)
3521         m_elementData = UniqueElementData::create();
3522     else
3523         m_elementData = downcast<ShareableElementData>(*m_elementData).makeUniqueCopy();
3524 }
3525
3526 bool Element::hasPendingResources() const
3527 {
3528     return hasRareData() && elementRareData()->hasPendingResources();
3529 }
3530
3531 void Element::setHasPendingResources()
3532 {
3533     ensureElementRareData().setHasPendingResources(true);
3534 }
3535
3536 void Element::clearHasPendingResources()
3537 {
3538     if (!hasRareData())
3539         return;
3540     elementRareData()->setHasPendingResources(false);
3541 }
3542
3543 bool Element::hasCSSAnimation() const
3544 {
3545     return hasRareData() && elementRareData()->hasCSSAnimation();
3546 }
3547
3548 void Element::setHasCSSAnimation()
3549 {
3550     ensureElementRareData().setHasCSSAnimation(true);
3551 }
3552
3553 void Element::clearHasCSSAnimation()
3554 {
3555     if (!hasRareData())
3556         return;
3557     elementRareData()->setHasCSSAnimation(false);
3558 }
3559
3560 bool Element::canContainRangeEndPoint() const
3561 {
3562     return !equalLettersIgnoringASCIICase(attributeWithoutSynchronization(roleAttr), "img");
3563 }
3564
3565 String Element::completeURLsInAttributeValue(const URL& base, const Attribute& attribute) const
3566 {
3567     return URL(base, attribute.value()).string();
3568 }
3569
3570 ExceptionOr<Node*> Element::insertAdjacent(const String& where, Ref<Node>&& newChild)
3571 {
3572     // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
3573     // a document fragment is created and the elements appended in the correct order. This document
3574     // fragment isn't returned anywhere.
3575     //
3576     // This is impossible for us to implement as the DOM tree does not allow for such structures,
3577     // Opera also appears to disallow such usage.
3578
3579     if (equalLettersIgnoringASCIICase(where, "beforebegin")) {
3580         auto* parent = this->parentNode();
3581         if (!parent)
3582             return nullptr;
3583         auto result = parent->insertBefore(newChild, this);
3584         if (result.hasException())
3585             return result.releaseException();
3586         return newChild.ptr();
3587     }
3588
3589     if (equalLettersIgnoringASCIICase(where, "afterbegin")) {
3590         auto result = insertBefore(newChild, firstChild());
3591         if (result.hasException())
3592             return result.releaseException();
3593         return newChild.ptr();
3594     }
3595
3596     if (equalLettersIgnoringASCIICase(where, "beforeend")) {
3597         auto result = appendChild(newChild);
3598         if (result.hasException())
3599             return result.releaseException();
3600         return newChild.ptr();
3601     }
3602
3603     if (equalLettersIgnoringASCIICase(where, "afterend")) {
3604         auto* parent = this->parentNode();
3605         if (!parent)
3606             return nullptr;
3607         auto result = parent->insertBefore(newChild, nextSibling());
3608         if (result.hasException())
3609             return result.releaseException();
3610         return newChild.ptr();
3611     }
3612
3613     return Exception { SyntaxError };
3614 }
3615
3616 ExceptionOr<Element*> Element::insertAdjacentElement(const String& where, Element& newChild)
3617 {
3618     auto result = insertAdjacent(where, newChild);
3619     if (result.hasException())
3620         return result.releaseException();
3621     return downcast<Element>(result.releaseReturnValue());
3622 }
3623
3624 // Step 1 of https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml.
3625 static ExceptionOr<ContainerNode&> contextNodeForInsertion(const String& where, Element& element)
3626 {
3627     if (equalLettersIgnoringASCIICase(where, "beforebegin") || equalLettersIgnoringASCIICase(where, "afterend")) {
3628         auto* parent = element.parentNode();
3629         if (!parent || is<Document>(*parent))
3630             return Exception { NoModificationAllowedError };
3631         return *parent;
3632     }
3633     if (equalLettersIgnoringASCIICase(where, "afterbegin") || equalLettersIgnoringASCIICase(where, "beforeend"))
3634         return element;
3635     return Exception { SyntaxError };
3636 }
3637
3638 // Step 2 of https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml.
3639 static ExceptionOr<Ref<Element>> contextElementForInsertion(const String& where, Element& element)
3640 {
3641     auto contextNodeResult = contextNodeForInsertion(where, element);
3642     if (contextNodeResult.hasException())
3643         return contextNodeResult.releaseException();
3644     auto& contextNode = contextNodeResult.releaseReturnValue();
3645     if (!is<Element>(contextNode) || (contextNode.document().isHTMLDocument() && is<HTMLHtmlElement>(contextNode)))
3646         return Ref<Element> { HTMLBodyElement::create(contextNode.document()) };
3647     return Ref<Element> { downcast<Element>(contextNode) };
3648 }
3649
3650 // https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml
3651 ExceptionOr<void> Element::insertAdjacentHTML(const String& where, const String& markup)
3652 {
3653     // Steps 1 and 2.
3654     auto contextElement = contextElementForInsertion(where, *this);
3655     if (contextElement.hasException())
3656         return contextElement.releaseException();
3657     // Step 3.
3658     auto fragment = createFragmentForInnerOuterHTML(contextElement.releaseReturnValue(), markup, AllowScriptingContent);
3659     if (fragment.hasException())
3660         return fragment.releaseException();
3661     // Step 4.
3662     auto result = insertAdjacent(where, fragment.releaseReturnValue());
3663     if (result.hasException())
3664         return result.releaseException();
3665     return { };
3666 }
3667
3668 ExceptionOr<void> Element::insertAdjacentText(const String& where, const String& text)
3669 {
3670     auto result = insertAdjacent(where, document().createTextNode(text));
3671     if (result.hasException())
3672         return result.releaseException();
3673     return { };
3674 }
3675
3676 Element* Element::findAnchorElementForLink(String& outAnchorName)
3677 {
3678     if (!isLink())
3679         return nullptr;
3680
3681     const AtomicString& href = attributeWithoutSynchronization(HTMLNames::hrefAttr);
3682     if (href.isNull())
3683         return nullptr;
3684
3685     Document& document = this->document();
3686     URL url = document.completeURL(href);
3687     if (!url.isValid())
3688         return nullptr;
3689
3690     if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(url, document.baseURL())) {
3691         outAnchorName = url.fragmentIdentifier();
3692         return document.findAnchor(outAnchorName);
3693     }
3694
3695     return nullptr;
3696 }
3697
3698 } // namespace WebCore