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