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