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