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