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