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