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