/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Peter Kelly (pmk@post.com)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2007 David Smith (catfish.man@gmail.com)
 * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
 *           (C) 2007 Eric Seidel (eric@webkit.org)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "Element.h"

#include "AXObjectCache.h"
#include "Attr.h"
#include "AttributeChangeInvalidation.h"
#include "CSSParser.h"
#include "ChildChangeInvalidation.h"
#include "ChildListMutationScope.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "ClassChangeInvalidation.h"
#include "ComposedTreeAncestorIterator.h"
#include "ComposedTreeIterator.h"
#include "ComputedStylePropertyMapReadOnly.h"
#include "ContainerNodeAlgorithms.h"
#include "CustomElementReactionQueue.h"
#include "CustomElementRegistry.h"
#include "DOMRect.h"
#include "DOMRectList.h"
#include "DOMTokenList.h"
#include "DOMWindow.h"
#include "DocumentInlines.h"
#include "DocumentSharedObjectPool.h"
#include "Editing.h"
#include "ElementAnimationRareData.h"
#include "ElementInlines.h"
#include "ElementIterator.h"
#include "ElementRareData.h"
#include "EventDispatcher.h"
#include "EventHandler.h"
#include "EventLoop.h"
#include "EventNames.h"
#include "FocusController.h"
#include "FocusEvent.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "FrameView.h"
#include "FullscreenManager.h"
#include "GetAnimationsOptions.h"
#include "HTMLBodyElement.h"
#include "HTMLCanvasElement.h"
#include "HTMLDialogElement.h"
#include "HTMLDocument.h"
#include "HTMLHtmlElement.h"
#include "HTMLLabelElement.h"
#include "HTMLNameCollection.h"
#include "HTMLObjectElement.h"
#include "HTMLOptGroupElement.h"
#include "HTMLOptionElement.h"
#include "HTMLParserIdioms.h"
#include "HTMLScriptElement.h"
#include "HTMLSelectElement.h"
#include "HTMLTemplateElement.h"
#include "IdChangeInvalidation.h"
#include "IdTargetObserverRegistry.h"
#include "InspectorInstrumentation.h"
#include "JSLazyEventListener.h"
#include "KeyboardEvent.h"
#include "KeyframeAnimationOptions.h"
#include "KeyframeEffect.h"
#include "Logging.h"
#include "MutationObserverInterestGroup.h"
#include "MutationRecord.h"
#include "NodeRenderStyle.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "PointerCaptureController.h"
#include "PointerEvent.h"
#include "PointerLockController.h"
#include "PseudoClassChangeInvalidation.h"
#include "Quirks.h"
#include "RenderFragmentedFlow.h"
#include "RenderLayer.h"
#include "RenderLayerBacking.h"
#include "RenderLayerCompositor.h"
#include "RenderLayerScrollableArea.h"
#include "RenderListBox.h"
#include "RenderTheme.h"
#include "RenderTreeUpdater.h"
#include "RenderView.h"
#include "RenderWidget.h"
#include "RuntimeEnabledFeatures.h"
#include "SVGDocumentExtensions.h"
#include "SVGElementTypeHelpers.h"
#include "SVGNames.h"
#include "SVGSVGElement.h"
#include "SVGScriptElement.h"
#include "ScriptDisallowedScope.h"
#include "ScrollIntoViewOptions.h"
#include "ScrollLatchingController.h"
#include "SecurityPolicyViolationEvent.h"
#include "SelectorQuery.h"
#include "Settings.h"
#include "ShadowRootInit.h"
#include "SimulatedClick.h"
#include "SlotAssignment.h"
#include "StyleInvalidator.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
#include "StyleScope.h"
#include "StyleTreeResolver.h"
#include "TextIterator.h"
#include "TouchAction.h"
#include "VoidCallback.h"
#include "WebAnimation.h"
#include "WebAnimationTypes.h"
#include "WheelEvent.h"
#include "XLinkNames.h"
#include "XMLNSNames.h"
#include "XMLNames.h"
#include "markup.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>
#include <wtf/text/TextStream.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(Element);

using namespace HTMLNames;
using namespace XMLNames;

static HashMap<Element*, Vector<RefPtr<Attr>>>& attrNodeListMap()
{
    static NeverDestroyed<HashMap<Element*, Vector<RefPtr<Attr>>>> map;
    return map;
}

static Vector<RefPtr<Attr>>* attrNodeListForElement(Element& element)
{
    if (!element.hasSyntheticAttrChildNodes())
        return nullptr;
    ASSERT(attrNodeListMap().contains(&element));
    return &attrNodeListMap().find(&element)->value;
}

static Vector<RefPtr<Attr>>& ensureAttrNodeListForElement(Element& element)
{
    if (element.hasSyntheticAttrChildNodes()) {
        ASSERT(attrNodeListMap().contains(&element));
        return attrNodeListMap().find(&element)->value;
    }
    ASSERT(!attrNodeListMap().contains(&element));
    element.setHasSyntheticAttrChildNodes(true);
    return attrNodeListMap().add(&element, Vector<RefPtr<Attr>>()).iterator->value;
}

static void removeAttrNodeListForElement(Element& element)
{
    ASSERT(element.hasSyntheticAttrChildNodes());
    ASSERT(attrNodeListMap().contains(&element));
    attrNodeListMap().remove(&element);
    element.setHasSyntheticAttrChildNodes(false);
}

static Attr* findAttrNodeInList(Vector<RefPtr<Attr>>& attrNodeList, const QualifiedName& name)
{
    for (auto& node : attrNodeList) {
        if (node->qualifiedName().matches(name))
            return node.get();
    }
    return nullptr;
}

static Attr* findAttrNodeInList(Vector<RefPtr<Attr>>& attrNodeList, const AtomString& localName, bool shouldIgnoreAttributeCase)
{
    const AtomString& caseAdjustedName = shouldIgnoreAttributeCase ? localName.convertToASCIILowercase() : localName;
    for (auto& node : attrNodeList) {
        if (node->qualifiedName().localName() == caseAdjustedName)
            return node.get();
    }
    return nullptr;
}

static bool shouldAutofocus(const Element& element)
{
    if (!element.hasAttributeWithoutSynchronization(HTMLNames::autofocusAttr))
        return false;

    auto& document = element.document();
    if (!element.isConnected() || !document.hasBrowsingContext())
        return false;
    if (document.isSandboxed(SandboxAutomaticFeatures)) {
        // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
        document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked autofocusing on a form control because the form's frame is sandboxed and the 'allow-scripts' permission is not set."_s);
        return false;
    }
    if (!document.frame()->isMainFrame() && !document.topOrigin().isSameOriginDomain(document.securityOrigin())) {
        document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked autofocusing on a form control in a cross-origin subframe."_s);
        return false;
    }

    if (document.topDocument().isAutofocusProcessed())
        return false;

    return true;
}

Ref<Element> Element::create(const QualifiedName& tagName, Document& document)
{
    return adoptRef(*new Element(tagName, document, CreateElement));
}

Element::Element(const QualifiedName& tagName, Document& document, ConstructionType type)
    : ContainerNode(document, type)
    , m_tagName(tagName)
{
}

Element::~Element()
{
    ASSERT(!beforePseudoElement());
    ASSERT(!afterPseudoElement());

    disconnectFromIntersectionObservers();

    disconnectFromResizeObservers();

    removeShadowRoot();

    if (hasSyntheticAttrChildNodes())
        detachAllAttrNodesFromElement();

#if ENABLE(CSS_TYPED_OM)
    if (hasRareData()) {
        if (auto* map = elementRareData()->attributeStyleMap())
            map->clearElement();
    }
#endif

    if (hasPendingResources()) {
        document().accessSVGExtensions().removeElementFromPendingResources(*this);
        ASSERT(!hasPendingResources());
    }
}

inline ElementRareData& Element::ensureElementRareData()
{
    return static_cast<ElementRareData&>(ensureRareData());
}

inline void Node::setTabIndexState(TabIndexState state)
{
    auto bitfields = rareDataBitfields();
    bitfields.tabIndexState = static_cast<uint16_t>(state);
    setRareDataBitfields(bitfields);
}

void Element::setTabIndexExplicitly(std::optional<int> tabIndex)
{
    if (!tabIndex) {
        setTabIndexState(TabIndexState::NotSet);
        return;
    }
    setTabIndexState([this, value = tabIndex.value()]() {
        switch (value) {
        case 0:
            return TabIndexState::Zero;
        case -1:
            return TabIndexState::NegativeOne;
        default:
            ensureElementRareData().setUnusualTabIndex(value);
            return TabIndexState::InRareData;
        }
    }());
}

std::optional<int> Element::tabIndexSetExplicitly() const
{
    switch (tabIndexState()) {
    case TabIndexState::NotSet:
        return std::nullopt;
    case TabIndexState::Zero:
        return 0;
    case TabIndexState::NegativeOne:
        return -1;
    case TabIndexState::InRareData:
        ASSERT(hasRareData());
        return elementRareData()->unusualTabIndex();
    }
    ASSERT_NOT_REACHED();
    return std::nullopt;
}

int Element::defaultTabIndex() const
{
    return -1;
}

bool Element::isNonceable() const
{
    // https://www.w3.org/TR/CSP3/#is-element-nonceable
    if (elementRareData()->nonce().isNull())
        return false;

    if (hasDuplicateAttribute())
        return false;

    if (hasAttributes()
        && (is<HTMLScriptElement>(*this) || is<SVGScriptElement>(*this))) {
        static constexpr auto scriptString = "<script"_s;
        static constexpr auto styleString = "<style"_s;

        for (const auto& attribute : attributesIterator()) {
            auto name = attribute.localName().convertToASCIILowercase();
            auto value = attribute.value().convertToASCIILowercase();
            if (name.contains(scriptString)
                || name.contains(styleString)
                || value.contains(scriptString)
                || value.contains(styleString))
                return false;
        }
    }

    return true;
}

const AtomString& Element::nonce() const
{
    if (hasRareData() && isNonceable())
        return elementRareData()->nonce();

    return emptyAtom();
}

void Element::setNonce(const AtomString& newValue)
{
    if (newValue == emptyAtom() && !hasRareData())
        return;

    ensureElementRareData().setNonce(newValue);
}

void Element::hideNonce()
{
    // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#nonce-attributes
    if (!isConnected())
        return;

    const auto& csp = document().contentSecurityPolicy();
    if (!csp->isHeaderDelivered())
        return;

    // Retain previous IDL nonce.
    AtomString currentNonce = nonce();

    if (!getAttribute(nonceAttr).isEmpty())
        setAttribute(nonceAttr, emptyAtom());

    setNonce(currentNonce);
}

bool Element::supportsFocus() const
{
    return !!tabIndexSetExplicitly();
}

RefPtr<Element> Element::focusDelegate()
{
    return this;
}

int Element::tabIndexForBindings() const
{
    return valueOrCompute(tabIndexSetExplicitly(), [&] { return defaultTabIndex(); });
}

void Element::setTabIndexForBindings(int value)
{
    setIntegralAttribute(tabindexAttr, value);
}

bool Element::isKeyboardFocusable(KeyboardEvent*) const
{
    if (!(isFocusable() && !shouldBeIgnoredInSequentialFocusNavigation() && tabIndexSetExplicitly().value_or(0) >= 0))
        return false;
    if (auto* root = shadowRoot()) {
        if (root->delegatesFocus())
            return false;
    }
    return true;
}

bool Element::isMouseFocusable() const
{
    return isFocusable();
}

bool Element::shouldUseInputMethod()
{
    return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) != Editability::ReadOnly;
}

static bool isForceEvent(const PlatformMouseEvent& platformEvent)
{
    return platformEvent.type() == PlatformEvent::MouseForceChanged || platformEvent.type() == PlatformEvent::MouseForceDown || platformEvent.type() == PlatformEvent::MouseForceUp;
}

static bool isCompatibilityMouseEvent(const MouseEvent& mouseEvent)
{
    // https://www.w3.org/TR/pointerevents/#compatibility-mapping-with-mouse-events
    const auto& type = mouseEvent.type();
    auto& eventNames = WebCore::eventNames();
    return type != eventNames.clickEvent && type != eventNames.mouseoverEvent && type != eventNames.mouseoutEvent && type != eventNames.mouseenterEvent && type != eventNames.mouseleaveEvent;
}

enum class ShouldIgnoreMouseEvent : bool { No, Yes };
static ShouldIgnoreMouseEvent dispatchPointerEventIfNeeded(Element& element, const MouseEvent& mouseEvent, const PlatformMouseEvent& platformEvent, bool& didNotSwallowEvent)
{
    if (auto* page = element.document().page()) {
        auto& pointerCaptureController = page->pointerCaptureController();
#if ENABLE(TOUCH_EVENTS)
        if (platformEvent.pointerId() != mousePointerID && mouseEvent.type() != eventNames().clickEvent && pointerCaptureController.preventsCompatibilityMouseEventsForIdentifier(platformEvent.pointerId()))
            return ShouldIgnoreMouseEvent::Yes;
#else
        UNUSED_PARAM(platformEvent);
#endif
        if (platformEvent.syntheticClickType() != NoTap)
            return ShouldIgnoreMouseEvent::No;

        if (auto pointerEvent = pointerCaptureController.pointerEventForMouseEvent(mouseEvent, platformEvent.pointerId(), platformEvent.pointerType())) {
            pointerCaptureController.dispatchEvent(*pointerEvent, &element);
            if (isCompatibilityMouseEvent(mouseEvent) && pointerCaptureController.preventsCompatibilityMouseEventsForIdentifier(pointerEvent->pointerId()))
                return ShouldIgnoreMouseEvent::Yes;
            if (pointerEvent->defaultPrevented() || pointerEvent->defaultHandled()) {
                didNotSwallowEvent = false;
                if (pointerEvent->type() == eventNames().pointerdownEvent)
                    return ShouldIgnoreMouseEvent::Yes;
            }
        }
    }

    return ShouldIgnoreMouseEvent::No;
}

bool Element::dispatchMouseEvent(const PlatformMouseEvent& platformEvent, const AtomString& eventType, int detail, Element* relatedTarget, IsSyntheticClick isSyntheticClick)
{
    if (isDisabledFormControl())
        return false;

    if (isForceEvent(platformEvent) && !document().hasListenerTypeForEventType(platformEvent.type()))
        return false;

    Ref<MouseEvent> mouseEvent = MouseEvent::create(eventType, document().windowProxy(), platformEvent, detail, relatedTarget);

    if (mouseEvent->type().isEmpty())
        return true; // Shouldn't happen.

    Ref protectedThis { *this };
    bool didNotSwallowEvent = true;

    if (dispatchPointerEventIfNeeded(*this, mouseEvent.get(), platformEvent, didNotSwallowEvent) == ShouldIgnoreMouseEvent::Yes)
        return false;
    
    auto isParentProcessAFullWebBrowser = false;
#if PLATFORM(IOS_FAMILY)
    if (Frame* frame = document().frame())
        isParentProcessAFullWebBrowser = frame->loader().client().isParentProcessAFullWebBrowser();
#elif PLATFORM(MAC)
    isParentProcessAFullWebBrowser = MacApplication::isSafari();
#endif
    if (Quirks::StorageAccessResult::ShouldCancelEvent == document().quirks().triggerOptionalStorageAccessQuirk(*this, platformEvent, eventType, detail, relatedTarget, isParentProcessAFullWebBrowser, isSyntheticClick))
        return false;

    ASSERT(!mouseEvent->target() || mouseEvent->target() != relatedTarget);
    dispatchEvent(mouseEvent);
    if (mouseEvent->defaultPrevented() || mouseEvent->defaultHandled())
        didNotSwallowEvent = false;

    if (mouseEvent->type() == eventNames().clickEvent && mouseEvent->detail() == 2) {
        // Special case: If it's a double click event, we also send the dblclick event. This is not part
        // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
        // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
        // FIXME: Is it okay that mouseEvent may have been mutated by scripts via initMouseEvent in dispatchEvent above?
        Ref<MouseEvent> doubleClickEvent = MouseEvent::create(eventNames().dblclickEvent,
            mouseEvent->bubbles() ? Event::CanBubble::Yes : Event::CanBubble::No,
            mouseEvent->cancelable() ? Event::IsCancelable::Yes : Event::IsCancelable::No,
            Event::IsComposed::Yes,
            mouseEvent->view(), mouseEvent->detail(),
            mouseEvent->screenX(), mouseEvent->screenY(), mouseEvent->clientX(), mouseEvent->clientY(),
            mouseEvent->modifierKeys(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->syntheticClickType(), relatedTarget);

        if (mouseEvent->defaultHandled())
            doubleClickEvent->setDefaultHandled();

        dispatchEvent(doubleClickEvent);
        if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
            return false;
    }
    return didNotSwallowEvent;
}

bool Element::dispatchWheelEvent(const PlatformWheelEvent& platformEvent, OptionSet<EventHandling>& processing, Event::IsCancelable isCancelable)
{
    auto event = WheelEvent::create(platformEvent, document().windowProxy(), isCancelable);

    // Events with no deltas are important because they convey platform information about scroll gestures
    // and momentum beginning or ending. However, those events should not be sent to the DOM since some
    // websites will break. They need to be dispatched because dispatching them will call into the default
    // event handler, and our platform code will correctly handle the phase changes. Calling stopPropagation()
    // will prevent the event from being sent to the DOM, but will still call the default event handler.
    // FIXME: Move this logic into WheelEvent::create.
    if (platformEvent.delta().isZero())
        event->stopPropagation();
    else
        processing.add(EventHandling::DispatchedToDOM);

    dispatchEvent(event);
    
    LOG_WITH_STREAM(Scrolling, stream << "Element " << *this << " dispatchWheelEvent: (cancelable " << event->cancelable() << ") defaultPrevented " << event->defaultPrevented() << " defaultHandled " << event->defaultHandled());
    
    if (event->defaultPrevented())
        processing.add(EventHandling::DefaultPrevented);

    if (event->defaultHandled())
        processing.add(EventHandling::DefaultHandled);

    return !event->defaultPrevented() && !event->defaultHandled();
}

bool Element::dispatchKeyEvent(const PlatformKeyboardEvent& platformEvent)
{
    auto event = KeyboardEvent::create(platformEvent, document().windowProxy());

    if (Frame* frame = document().frame()) {
        if (frame->eventHandler().accessibilityPreventsEventPropagation(event))
            event->stopPropagation();
    }

    dispatchEvent(event);
    return !event->defaultPrevented() && !event->defaultHandled();
}

bool Element::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickVisualOptions visualOptions)
{
    return simulateClick(*this, underlyingEvent, eventOptions, visualOptions, SimulatedClickSource::UserAgent);
}

Ref<Node> Element::cloneNodeInternal(Document& targetDocument, CloningOperation type)
{
    switch (type) {
    case CloningOperation::OnlySelf:
    case CloningOperation::SelfWithTemplateContent:
        return cloneElementWithoutChildren(targetDocument);
    case CloningOperation::Everything:
        break;
    }
    return cloneElementWithChildren(targetDocument);
}

Ref<Element> Element::cloneElementWithChildren(Document& targetDocument)
{
    Ref<Element> clone = cloneElementWithoutChildren(targetDocument);
    cloneChildNodes(clone);
    return clone;
}

Ref<Element> Element::cloneElementWithoutChildren(Document& targetDocument)
{
    Ref<Element> clone = cloneElementWithoutAttributesAndChildren(targetDocument);

    // This will catch HTML elements in the wrong namespace that are not correctly copied.
    // This is a sanity check as HTML overloads some of the DOM methods.
    ASSERT(isHTMLElement() == clone->isHTMLElement());

    clone->cloneDataFromElement(*this);
    return clone;
}

Ref<Element> Element::cloneElementWithoutAttributesAndChildren(Document& targetDocument)
{
    return targetDocument.createElement(tagQName(), false);
}

Ref<Attr> Element::detachAttribute(unsigned index)
{
    ASSERT(elementData());

    const Attribute& attribute = elementData()->attributeAt(index);

    RefPtr<Attr> attrNode = attrIfExists(attribute.name());
    if (attrNode)
        detachAttrNodeFromElementWithValue(attrNode.get(), attribute.value());
    else
        attrNode = Attr::create(document(), attribute.name(), attribute.value());

    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
    return attrNode.releaseNonNull();
}

bool Element::removeAttribute(const QualifiedName& name)
{
    if (!elementData())
        return false;

    unsigned index = elementData()->findAttributeIndexByName(name);
    if (index == ElementData::attributeNotFound)
        return false;

    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
    return true;
}

void Element::setBooleanAttribute(const QualifiedName& name, bool value)
{
    if (value)
        setAttribute(name, emptyAtom());
    else
        removeAttribute(name);
}

NamedNodeMap& Element::attributes() const
{
    ElementRareData& rareData = const_cast<Element*>(this)->ensureElementRareData();
    if (NamedNodeMap* attributeMap = rareData.attributeMap())
        return *attributeMap;

    rareData.setAttributeMap(makeUnique<NamedNodeMap>(const_cast<Element&>(*this)));
    return *rareData.attributeMap();
}

Node::NodeType Element::nodeType() const
{
    return ELEMENT_NODE;
}

bool Element::hasAttribute(const QualifiedName& name) const
{
    return hasAttributeNS(name.namespaceURI(), name.localName());
}

void Element::synchronizeAllAttributes() const
{
    if (!elementData())
        return;
    if (elementData()->styleAttributeIsDirty()) {
        ASSERT(isStyledElement());
        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
    }
    
    if (isSVGElement())
        downcast<SVGElement>(const_cast<Element&>(*this)).synchronizeAllAttributes();
}

ALWAYS_INLINE void Element::synchronizeAttribute(const QualifiedName& name) const
{
    if (!elementData())
        return;
    if (UNLIKELY(name == styleAttr && elementData()->styleAttributeIsDirty())) {
        ASSERT_WITH_SECURITY_IMPLICATION(isStyledElement());
        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
        return;
    }

    if (isSVGElement())
        downcast<SVGElement>(const_cast<Element&>(*this)).synchronizeAttribute(name);
}

static ALWAYS_INLINE bool isStyleAttribute(const Element& element, const AtomString& attributeLocalName)
{
    if (shouldIgnoreAttributeCase(element))
        return equalLettersIgnoringASCIICase(attributeLocalName, "style"_s);
    return attributeLocalName == styleAttr->localName();
}

ALWAYS_INLINE void Element::synchronizeAttribute(const AtomString& localName) const
{
    // This version of synchronizeAttribute() is streamlined for the case where you don't have a full QualifiedName,
    // e.g when called from DOM API.
    if (!elementData())
        return;
    if (elementData()->styleAttributeIsDirty() && isStyleAttribute(*this, localName)) {
        ASSERT_WITH_SECURITY_IMPLICATION(isStyledElement());
        static_cast<const StyledElement*>(this)->synchronizeStyleAttributeInternal();
        return;
    }

    if (isSVGElement())
        downcast<SVGElement>(const_cast<Element&>(*this)).synchronizeAttribute(QualifiedName(nullAtom(), localName, nullAtom()));
}

const AtomString& Element::getAttribute(const QualifiedName& name) const
{
    if (!elementData())
        return nullAtom();
    synchronizeAttribute(name);
    if (const Attribute* attribute = findAttributeByName(name))
        return attribute->value();
    return nullAtom();
}

Vector<String> Element::getAttributeNames() const
{
    Vector<String> attributesVector;
    if (!hasAttributes())
        return attributesVector;

    auto attributes = attributesIterator();
    attributesVector.reserveInitialCapacity(attributes.attributeCount());
    for (auto& attribute : attributes)
        attributesVector.uncheckedAppend(attribute.name().toString());
    return attributesVector;
}

bool Element::isFocusable() const
{
    if (!isConnected() || !supportsFocus())
        return false;

    if (!renderer()) {
        // Elements in canvas fallback content are not rendered, but they are allowed to be
        // focusable as long as their canvas is displayed and visible.
        if (auto* canvas = ancestorsOfType<HTMLCanvasElement>(*this).first())
            return canvas->isFocusableWithoutResolvingFullStyle();
    }

    return isFocusableWithoutResolvingFullStyle();
}

bool Element::isUserActionElementInActiveChain() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().isInActiveChain(*this);
}

bool Element::isUserActionElementActive() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().isActive(*this);
}

bool Element::isUserActionElementFocused() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().isFocused(*this);
}

bool Element::isUserActionElementHovered() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().isHovered(*this);
}

bool Element::isUserActionElementDragged() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().isBeingDragged(*this);
}

bool Element::isUserActionElementHasFocusVisible() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().hasFocusVisible(*this);
}

bool Element::isUserActionElementHasFocusWithin() const
{
    ASSERT(isUserActionElement());
    return document().userActionElements().hasFocusWithin(*this);
}

void Element::setActive(bool value, bool pause, Style::InvalidationScope invalidationScope)
{
    if (value == active())
        return;
    {
        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassActive, value, invalidationScope);
        document().userActionElements().setActive(*this, value);
    }

    if (!renderer())
        return;

    bool reactsToPress = false;
    if (renderer()->style().hasEffectiveAppearance() && renderer()->theme().stateChanged(*renderer(), ControlStates::States::Pressed))
        reactsToPress = true;

    // The rest of this function implements a feature that only works if the
    // platform supports immediate invalidations on the ChromeClient, so bail if
    // that isn't supported.
    if (!document().page()->chrome().client().supportsImmediateInvalidation())
        return;

    if (reactsToPress && pause) {
        // The delay here is subtle. It relies on an assumption, namely that the amount of time it takes
        // to repaint the "down" state of the control is about the same time as it would take to repaint the
        // "up" state. Once you assume this, you can just delay for 100ms - that time (assuming that after you
        // leave this method, it will be about that long before the flush of the up state happens again).
#ifdef HAVE_FUNC_USLEEP
        MonotonicTime startTime = MonotonicTime::now();
#endif

        document().updateStyleIfNeeded();

        // Do an immediate repaint.
        if (renderer())
            renderer()->repaint();

        // FIXME: Come up with a less ridiculous way of doing this.
#ifdef HAVE_FUNC_USLEEP
        // Now pause for a small amount of time (1/10th of a second from before we repainted in the pressed state)
        Seconds remainingTime = 100_ms - (MonotonicTime::now() - startTime);
        if (remainingTime > 0_s)
            usleep(static_cast<useconds_t>(remainingTime.microseconds()));
#endif
    }
}

static bool shouldAlwaysHaveFocusVisibleWhenFocused(const Element& element)
{
    return element.isTextField() || element.isContentEditable() || is<HTMLSelectElement>(element);
}

void Element::setFocus(bool value, FocusVisibility visibility)
{
    if (value == focused())
        return;
    
    Style::PseudoClassChangeInvalidation focusStyleInvalidation(*this, { { CSSSelector::PseudoClassFocus, value }, { CSSSelector::PseudoClassFocusVisible, value } });
    document().userActionElements().setFocused(*this, value);

    // Shadow host with a slot that contain focused element is not considered focused.
    for (auto* root = containingShadowRoot(); root; root = root->host()->containingShadowRoot()) {
        root->setContainsFocusedElement(value);
        root->host()->invalidateStyle();
    }

    for (auto* element = this; element; element = element->parentElementInComposedTree())
        element->setHasFocusWithin(value);

    setHasFocusVisible(value && (visibility == FocusVisibility::Visible || shouldAlwaysHaveFocusVisibleWhenFocused(*this)));
}

void Element::setHasFocusVisible(bool value)
{
    if (!document().settings().focusVisibleEnabled())
        return;

#if ASSERT_ENABLED
    ASSERT(!value || focused());
    ASSERT(!focused() || !shouldAlwaysHaveFocusVisibleWhenFocused(*this) || value);
#endif

    if (hasFocusVisible() == value)
        return;

    document().userActionElements().setHasFocusVisible(*this, value);
}

void Element::setHasFocusWithin(bool value)
{
    if (hasFocusWithin() == value)
        return;
    {
        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassFocusWithin, value);
        document().userActionElements().setHasFocusWithin(*this, value);
    }
}

void Element::setHovered(bool value, Style::InvalidationScope invalidationScope, HitTestRequest)
{
    if (value == hovered())
        return;
    {
        Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassHover, value, invalidationScope);
        document().userActionElements().setHovered(*this, value);
    }

    if (auto* style = renderStyle(); style && style->hasEffectiveAppearance())
        renderer()->theme().stateChanged(*renderer(), ControlStates::States::Hovered);
}

void Element::setBeingDragged(bool value)
{
    if (value == isBeingDragged())
        return;

    Style::PseudoClassChangeInvalidation styleInvalidation(*this, CSSSelector::PseudoClassDrag, value);
    document().userActionElements().setBeingDragged(*this, value);
}

inline ScrollAlignment toScrollAlignmentForInlineDirection(std::optional<ScrollLogicalPosition> position, WritingMode writingMode, bool isLTR)
{
    switch (position.value_or(ScrollLogicalPosition::Nearest)) {
    case ScrollLogicalPosition::Start: {
        switch (writingMode) {
        case WritingMode::TopToBottom:
        case WritingMode::BottomToTop: {
            return isLTR ? ScrollAlignment::alignLeftAlways : ScrollAlignment::alignRightAlways;
        }
        case WritingMode::LeftToRight:
        case WritingMode::RightToLeft: {
            return isLTR ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignBottomAlways;
        }
        default:
            ASSERT_NOT_REACHED();
            return ScrollAlignment::alignLeftAlways;
        }
    }
    case ScrollLogicalPosition::Center:
        return ScrollAlignment::alignCenterAlways;
    case ScrollLogicalPosition::End: {
        switch (writingMode) {
        case WritingMode::TopToBottom:
        case WritingMode::BottomToTop: {
            return isLTR ? ScrollAlignment::alignRightAlways : ScrollAlignment::alignLeftAlways;
        }
        case WritingMode::LeftToRight:
        case WritingMode::RightToLeft: {
            return isLTR ? ScrollAlignment::alignBottomAlways : ScrollAlignment::alignTopAlways;
        }
        default:
            ASSERT_NOT_REACHED();
            return ScrollAlignment::alignRightAlways;
        }
    }
    case ScrollLogicalPosition::Nearest:
        return ScrollAlignment::alignToEdgeIfNeeded;
    default:
        ASSERT_NOT_REACHED();
        return ScrollAlignment::alignToEdgeIfNeeded;
    }
}

inline ScrollAlignment toScrollAlignmentForBlockDirection(std::optional<ScrollLogicalPosition> position, WritingMode writingMode)
{
    switch (position.value_or(ScrollLogicalPosition::Start)) {
    case ScrollLogicalPosition::Start: {
        switch (writingMode) {
        case WritingMode::TopToBottom:
            return ScrollAlignment::alignTopAlways;
        case WritingMode::BottomToTop:
            return ScrollAlignment::alignBottomAlways;
        case WritingMode::LeftToRight:
            return ScrollAlignment::alignLeftAlways;
        case WritingMode::RightToLeft:
            return ScrollAlignment::alignRightAlways;
        default:
            ASSERT_NOT_REACHED();
            return ScrollAlignment::alignTopAlways;
        }
    }
    case ScrollLogicalPosition::Center:
        return ScrollAlignment::alignCenterAlways;
    case ScrollLogicalPosition::End: {
        switch (writingMode) {
        case WritingMode::TopToBottom:
            return ScrollAlignment::alignBottomAlways;
        case WritingMode::BottomToTop:
            return ScrollAlignment::alignTopAlways;
        case WritingMode::LeftToRight:
            return ScrollAlignment::alignRightAlways;
        case WritingMode::RightToLeft:
            return ScrollAlignment::alignLeftAlways;
        default:
            ASSERT_NOT_REACHED();
            return ScrollAlignment::alignBottomAlways;
        }
    }
    case ScrollLogicalPosition::Nearest:
        return ScrollAlignment::alignToEdgeIfNeeded;
    default:
        ASSERT_NOT_REACHED();
        return ScrollAlignment::alignToEdgeIfNeeded;
    }
}

void Element::scrollIntoView(std::optional<std::variant<bool, ScrollIntoViewOptions>>&& arg)
{
    document().updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return;

    bool insideFixed;
    LayoutRect absoluteBounds = renderer()->absoluteAnchorRectWithScrollMargin(&insideFixed);

    ScrollIntoViewOptions options;
    if (arg) {
        auto value = arg.value();
        if (std::holds_alternative<ScrollIntoViewOptions>(value))
            options = std::get<ScrollIntoViewOptions>(value);
        else if (!std::get<bool>(value))
            options.blockPosition = ScrollLogicalPosition::End;
    }

    auto writingMode = renderer()->style().writingMode();
    ScrollAlignment alignX = toScrollAlignmentForInlineDirection(options.inlinePosition, writingMode, renderer()->style().isLeftToRightDirection());
    ScrollAlignment alignY = toScrollAlignmentForBlockDirection(options.blockPosition, writingMode);
    alignX.disableLegacyHorizontalVisibilityThreshold();

    bool isHorizontal = renderer()->style().isHorizontalWritingMode();
    ScrollRectToVisibleOptions visibleOptions {
        SelectionRevealMode::Reveal,
        isHorizontal ? alignX : alignY,
        isHorizontal ? alignY : alignX,
        ShouldAllowCrossOriginScrolling::No,
        options.behavior.value_or(ScrollBehavior::Auto)
    };
    renderer()->scrollRectToVisible(absoluteBounds, insideFixed, visibleOptions);
}

void Element::scrollIntoView(bool alignToTop) 
{
    document().updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return;

    bool insideFixed;
    LayoutRect absoluteBounds = renderer()->absoluteAnchorRectWithScrollMargin(&insideFixed);

    // Align to the top / bottom and to the closest edge.
    auto alignY = alignToTop ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignBottomAlways;
    auto alignX = ScrollAlignment::alignToEdgeIfNeeded;
    alignX.disableLegacyHorizontalVisibilityThreshold();

    renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, alignX, alignY, ShouldAllowCrossOriginScrolling::No });
}

void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
{
    document().updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return;

    bool insideFixed;
    LayoutRect absoluteBounds = renderer()->absoluteAnchorRectWithScrollMargin(&insideFixed);

    auto alignY = centerIfNeeded ? ScrollAlignment::alignCenterIfNeeded : ScrollAlignment::alignToEdgeIfNeeded;
    auto alignX = centerIfNeeded ? ScrollAlignment::alignCenterIfNeeded : ScrollAlignment::alignToEdgeIfNeeded;
    alignX.disableLegacyHorizontalVisibilityThreshold();

    renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, alignX, alignY, ShouldAllowCrossOriginScrolling::No });
}

void Element::scrollIntoViewIfNotVisible(bool centerIfNotVisible)
{
    document().updateLayoutIgnorePendingStylesheets();
    
    if (!renderer())
        return;
    
    bool insideFixed;
    LayoutRect absoluteBounds = renderer()->absoluteAnchorRectWithScrollMargin(&insideFixed);
    if (centerIfNotVisible)
        renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible, ShouldAllowCrossOriginScrolling::No });
    else
        renderer()->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible, ShouldAllowCrossOriginScrolling::No });
}

void Element::scrollBy(const ScrollToOptions& options)
{
    ScrollToOptions scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(options, 0, 0);
    scrollToOptions.left.value() += scrollLeft();
    scrollToOptions.top.value() += scrollTop();
    scrollTo(scrollToOptions, ScrollClamping::Clamped, ScrollSnapPointSelectionMethod::Directional);
}

void Element::scrollBy(double x, double y)
{
    scrollBy(ScrollToOptions(x, y));
}

void Element::scrollTo(const ScrollToOptions& options, ScrollClamping clamping, ScrollSnapPointSelectionMethod snapPointSelectionMethod)
{
    LOG_WITH_STREAM(Scrolling, stream << "Element " << *this << " scrollTo " << options.left << ", " << options.top);

    if (!document().settings().CSSOMViewScrollingAPIEnabled()) {
        // If the element is the root element and document is in quirks mode, terminate these steps.
        // Note that WebKit always uses quirks mode document scrolling behavior. See Document::scrollingElement().
        if (this == document().documentElement())
            return;
    }
    
    if (auto* view = document().view())
        view->cancelScheduledScrollToFocusedElement();

    document().updateLayoutIgnorePendingStylesheets();

    if (document().scrollingElement() == this) {
        // If the element is the scrolling element and is not potentially scrollable,
        // invoke scroll() on window with options as the only argument, and terminate these steps.
        // FIXME: Scrolling an independently scrollable body is broken: webkit.org/b/161612.
        RefPtr window = document().domWindow();
        if (!window)
            return;

        window->scrollTo(options, clamping, snapPointSelectionMethod);
        return;
    }

    // If the element does not have any associated CSS layout box, the element has no associated scrolling box,
    // or the element has no overflow, terminate these steps.
    RenderBox* renderer = renderBox();
    if (!renderer || !renderer->hasNonVisibleOverflow())
        return;

    auto scrollToOptions = normalizeNonFiniteCoordinatesOrFallBackTo(options,
        adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer),
        adjustForAbsoluteZoom(renderer->scrollTop(), *renderer)
    );
    IntPoint scrollPosition(
        clampToInteger(scrollToOptions.left.value() * renderer->style().effectiveZoom()),
        clampToInteger(scrollToOptions.top.value() * renderer->style().effectiveZoom())
    );

    auto animated = useSmoothScrolling(scrollToOptions.behavior.value_or(ScrollBehavior::Auto), this) ? ScrollIsAnimated::Yes : ScrollIsAnimated::No;
    auto scrollPositionChangeOptions = ScrollPositionChangeOptions::createProgrammaticWithOptions(clamping, animated, snapPointSelectionMethod);
    renderer->setScrollPosition(scrollPosition, scrollPositionChangeOptions);
}

void Element::scrollTo(double x, double y)
{
    scrollTo(ScrollToOptions(x, y));
}

void Element::scrollByUnits(int units, ScrollGranularity granularity)
{
    document().updateLayoutIgnorePendingStylesheets();

    auto* renderer = this->renderer();
    if (!renderer)
        return;

    if (!renderer->hasNonVisibleOverflow())
        return;

    auto direction = units < 0 ? ScrollUp : ScrollDown;
    auto* stopElement = this;
    downcast<RenderBox>(*renderer).scroll(direction, granularity, std::abs(units), &stopElement);
}

void Element::scrollByLines(int lines)
{
    scrollByUnits(lines, ScrollGranularity::Line);
}

void Element::scrollByPages(int pages)
{
    scrollByUnits(pages, ScrollGranularity::Page);
}

static double localZoomForRenderer(const RenderElement& renderer)
{
    // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
    // other out, but the alternative is that we'd have to crawl up the whole render tree every
    // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
    double zoomFactor = 1;
    if (renderer.style().effectiveZoom() != 1) {
        // Need to find the nearest enclosing RenderElement that set up
        // a differing zoom, and then we divide our result by it to eliminate the zoom.
        const RenderElement* prev = &renderer;
        for (RenderElement* curr = prev->parent(); curr; curr = curr->parent()) {
            if (curr->style().effectiveZoom() != prev->style().effectiveZoom()) {
                zoomFactor = prev->style().zoom();
                break;
            }
            prev = curr;
        }
        if (prev->isRenderView())
            zoomFactor = prev->style().zoom();
    }
    return zoomFactor;
}

static int adjustContentsScrollPositionOrSizeForZoom(int value, const Frame& frame)
{
    double zoomFactor = frame.pageZoomFactor() * frame.frameScaleFactor();
    if (zoomFactor == 1)
        return value;
    // FIXME (webkit.org/b/189397): Why can't we just ceil/floor?
    // Needed because of truncation (rather than rounding) when scaling up.
    if (zoomFactor > 1)
        value++;
    return static_cast<int>(value / zoomFactor);
}

enum LegacyCSSOMElementMetricsRoundingStrategy { Round, Floor };

static int convertToNonSubpixelValue(double value, const LegacyCSSOMElementMetricsRoundingStrategy roundStrategy = Round)
{
    return roundStrategy == Round ? std::round(value) : std::floor(value);
}

static int adjustOffsetForZoomAndSubpixelLayout(RenderBoxModelObject& renderer, const LayoutUnit& offset)
{
    auto offsetLeft = LayoutUnit { roundToInt(offset) };
    double zoomFactor = localZoomForRenderer(renderer);
    if (zoomFactor == 1)
        return convertToNonSubpixelValue(offsetLeft, Floor);
    return convertToNonSubpixelValue(offsetLeft / zoomFactor, Round);
}

static HashSet<TreeScope*> collectAncestorTreeScopeAsHashSet(Node& node)
{
    HashSet<TreeScope*> ancestors;
    for (auto* currentScope = &node.treeScope(); currentScope; currentScope = currentScope->parentTreeScope())
        ancestors.add(currentScope);
    return ancestors;
}

int Element::offsetLeftForBindings()
{
    auto offset = offsetLeft();

    RefPtr parent = offsetParent();
    if (!parent || !parent->isInShadowTree())
        return offset;

    ASSERT(&parent->document() == &document());
    if (&parent->treeScope() == &treeScope())
        return offset;

    auto ancestorTreeScopes = collectAncestorTreeScopeAsHashSet(*this);
    while (parent && !ancestorTreeScopes.contains(&parent->treeScope())) {
        offset += parent->offsetLeft();
        parent = parent->offsetParent();
    }

    return offset;
}

int Element::offsetLeft()
{
    document().updateLayoutIgnorePendingStylesheets();
    if (RenderBoxModelObject* renderer = renderBoxModelObject())
        return adjustOffsetForZoomAndSubpixelLayout(*renderer, renderer->offsetLeft());
    return 0;
}

int Element::offsetTopForBindings()
{
    auto offset = offsetTop();

    RefPtr parent = offsetParent();
    if (!parent || !parent->isInShadowTree())
        return offset;

    ASSERT(&parent->document() == &document());
    if (&parent->treeScope() == &treeScope())
        return offset;

    auto ancestorTreeScopes = collectAncestorTreeScopeAsHashSet(*this);
    while (parent && !ancestorTreeScopes.contains(&parent->treeScope())) {
        offset += parent->offsetTop();
        parent = parent->offsetParent();
    }

    return offset;
}

int Element::offsetTop()
{
    document().updateLayoutIgnorePendingStylesheets();
    if (RenderBoxModelObject* renderer = renderBoxModelObject())
        return adjustOffsetForZoomAndSubpixelLayout(*renderer, renderer->offsetTop());
    return 0;
}

int Element::offsetWidth()
{
    document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
    if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
        auto offsetWidth = LayoutUnit { roundToInt(renderer->offsetWidth()) };
        return convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(offsetWidth, *renderer).toDouble());
    }
    return 0;
}

int Element::offsetHeight()
{
    document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
    if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
        auto offsetHeight = LayoutUnit { roundToInt(renderer->offsetHeight()) };
        return convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(offsetHeight, *renderer).toDouble());
    }
    return 0;
}

Element* Element::offsetParentForBindings()
{
    Element* element = offsetParent();
    if (!element || !element->isInShadowTree())
        return element;
    while (element && !isDescendantOrShadowDescendantOf(&element->rootNode()))
        element = element->offsetParent();
    return element;
}

Element* Element::offsetParent()
{
    document().updateLayoutIgnorePendingStylesheets();
    auto renderer = this->renderer();
    if (!renderer)
        return nullptr;
    auto offsetParent = renderer->offsetParent();
    if (!offsetParent)
        return nullptr;
    return offsetParent->element();
}

int Element::clientLeft()
{
    document().updateLayoutIgnorePendingStylesheets();

    if (auto* renderer = renderBox()) {
        auto clientLeft = LayoutUnit { roundToInt(renderer->clientLeft()) };
        return convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(clientLeft, *renderer).toDouble());
    }
    return 0;
}

int Element::clientTop()
{
    document().updateLayoutIgnorePendingStylesheets();

    if (auto* renderer = renderBox()) {
        auto clientTop = LayoutUnit { roundToInt(renderer->clientTop()) };
        return convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(clientTop, *renderer).toDouble());
    }
    return 0;
}

int Element::clientWidth()
{
    document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);

    if (!document().hasLivingRenderTree())
        return 0;

    RenderView& renderView = *document().renderView();

    // When in strict mode, clientWidth for the document element should return the width of the containing frame.
    // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
    bool inQuirksMode = document().inQuirksMode();
    if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().bodyOrFrameset() == this))
        return adjustForAbsoluteZoom(renderView.frameView().layoutWidth(), renderView);
    
    if (RenderBox* renderer = renderBox()) {
        auto clientWidth = LayoutUnit { roundToInt(renderer->clientWidth()) };
        // clientWidth/Height is the visual portion of the box content, not including
        // borders or scroll bars, but includes padding. And per
        // https://www.w3.org/TR/CSS2/tables.html#model,
        // table wrapper box is a principal block box that contains the table box
        // itself and any caption boxes, and table grid box is a block-level box that
        // contains the table's internal table boxes. When table's border is specified
        // in CSS, the border is added to table grid box, not table wrapper box.
        // Currently, WebKit doesn't have table wrapper box, and we are supposed to
        // retrieve clientWidth/Height from table wrapper box, not table grid box. So
        // when we retrieve clientWidth/Height, it includes table's border size.
        if (renderer->isTable())
            clientWidth += renderer->borderLeft() + renderer->borderRight();
        return convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(clientWidth, *renderer).toDouble());
    }
    return 0;
}

int Element::clientHeight()
{
    document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
    if (!document().hasLivingRenderTree())
        return 0;

    RenderView& renderView = *document().renderView();

    // When in strict mode, clientHeight for the document element should return the height of the containing frame.
    // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
    bool inQuirksMode = document().inQuirksMode();
    if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().bodyOrFrameset() == this))
        return adjustForAbsoluteZoom(renderView.frameView().layoutHeight(), renderView);

    if (RenderBox* renderer = renderBox()) {
        auto clientHeight = LayoutUnit { roundToInt(renderer->clientHeight()) };
        // clientWidth/Height is the visual portion of the box content, not including
        // borders or scroll bars, but includes padding. And per
        // https://www.w3.org/TR/CSS2/tables.html#model,
        // table wrapper box is a principal block box that contains the table box
        // itself and any caption boxes, and table grid box is a block-level box that
        // contains the table's internal table boxes. When table's border is specified
        // in CSS, the border is added to table grid box, not table wrapper box.
        // Currently, WebKit doesn't have table wrapper box, and we are supposed to
        // retrieve clientWidth/Height from table wrapper box, not table grid box. So
        // when we retrieve clientWidth/Height, it includes table's border size.
        if (renderer->isTable())
            clientHeight += renderer->borderTop() + renderer->borderBottom();
        return convertToNonSubpixelValue(adjustLayoutUnitForAbsoluteZoom(clientHeight, *renderer).toDouble());
    }
    return 0;
}

ALWAYS_INLINE Frame* Element::documentFrameWithNonNullView() const
{
    auto* frame = document().frame();
    return frame && frame->view() ? frame : nullptr;
}

int Element::scrollLeft()
{
    document().updateLayoutIgnorePendingStylesheets();

    if (document().scrollingElement() == this) {
        if (auto* frame = documentFrameWithNonNullView())
            return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsScrollPosition().x(), *frame);
        return 0;
    }

    if (auto* renderer = renderBox())
        return adjustForAbsoluteZoom(renderer->scrollLeft(), *renderer);
    return 0;
}

int Element::scrollTop()
{
    document().updateLayoutIgnorePendingStylesheets();

    if (document().scrollingElement() == this) {
        if (auto* frame = documentFrameWithNonNullView())
            return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsScrollPosition().y(), *frame);
        return 0;
    }

    if (RenderBox* renderer = renderBox())
        return adjustForAbsoluteZoom(renderer->scrollTop(), *renderer);
    return 0;
}

void Element::setScrollLeft(int newLeft)
{
    document().updateLayoutIgnorePendingStylesheets();

    auto options = ScrollPositionChangeOptions::createProgrammatic();
    options.animated = useSmoothScrolling(ScrollBehavior::Auto, this) ? ScrollIsAnimated::Yes : ScrollIsAnimated::No;

    if (document().scrollingElement() == this) {
        if (RefPtr frame = documentFrameWithNonNullView()) {
            IntPoint position(static_cast<int>(newLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), frame->view()->scrollY());
            frame->view()->setScrollPosition(position, options);
        }
        return;
    }

    if (WeakPtr renderer = renderBox()) {
        int clampedLeft = clampToInteger(newLeft * renderer->style().effectiveZoom());
        renderer->setScrollLeft(clampedLeft, options);
        if (auto* scrollableArea = renderer && renderer->layer() ? renderer->layer()->scrollableArea() : nullptr)
            scrollableArea->setScrollShouldClearLatchedState(true);
    }
}

void Element::setScrollTop(int newTop)
{
    document().updateLayoutIgnorePendingStylesheets();

    auto options = ScrollPositionChangeOptions::createProgrammatic();
    options.animated = useSmoothScrolling(ScrollBehavior::Auto, this) ? ScrollIsAnimated::Yes : ScrollIsAnimated::No;

    if (document().scrollingElement() == this) {
        if (RefPtr frame = documentFrameWithNonNullView()) {
            IntPoint position(frame->view()->scrollX(), static_cast<int>(newTop * frame->pageZoomFactor() * frame->frameScaleFactor()));
            frame->view()->setScrollPosition(position, options);
        }
        return;
    }

    if (WeakPtr renderer = renderBox()) {
        int clampedTop = clampToInteger(newTop * renderer->style().effectiveZoom());
        renderer->setScrollTop(clampedTop, options);
        if (auto* scrollableArea = renderer && renderer->layer() ? renderer->layer()->scrollableArea() : nullptr)
            scrollableArea->setScrollShouldClearLatchedState(true);
    }
}

int Element::scrollWidth()
{
    document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);

    if (document().scrollingElement() == this) {
        // FIXME (webkit.org/b/182289): updateLayoutIfDimensionsOutOfDate seems to ignore zoom level change.
        document().updateLayoutIgnorePendingStylesheets();
        if (auto* frame = documentFrameWithNonNullView())
            return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsWidth(), *frame);
        return 0;
    }

    if (auto* renderer = renderBox())
        return adjustForAbsoluteZoom(renderer->scrollWidth(), *renderer);
    return 0;
}

int Element::scrollHeight()
{
    document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);

    if (document().scrollingElement() == this) {
        // FIXME (webkit.org/b/182289): updateLayoutIfDimensionsOutOfDate seems to ignore zoom level change.
        document().updateLayoutIgnorePendingStylesheets();
        if (auto* frame = documentFrameWithNonNullView())
            return adjustContentsScrollPositionOrSizeForZoom(frame->view()->contentsHeight(), *frame);
        return 0;
    }

    if (auto* renderer = renderBox())
        return adjustForAbsoluteZoom(renderer->scrollHeight(), *renderer);
    return 0;
}

IntRect Element::boundsInRootViewSpace()
{
    document().updateLayoutIgnorePendingStylesheets();

    FrameView* view = document().view();
    if (!view)
        return IntRect();

    Vector<FloatQuad> quads;

    if (isSVGElement() && renderer()) {
        // Get the bounding rectangle from the SVG model.
        SVGElement& svgElement = downcast<SVGElement>(*this);
        if (auto localRect = svgElement.getBoundingBox())
            quads.append(renderer()->localToAbsoluteQuad(*localRect));
    } else {
        // Get the bounding rectangle from the box model.
        if (renderBoxModelObject())
            renderBoxModelObject()->absoluteQuads(quads);
    }

    return view->contentsToRootView(enclosingIntRect(unitedBoundingBoxes(quads)));
}

IntRect Element::boundingBoxInRootViewCoordinates() const
{
    if (RenderObject* renderer = this->renderer())
        return document().view()->contentsToRootView(renderer->absoluteBoundingBoxRect());
    return IntRect();
}

static bool layoutOverflowRectContainsAllDescendants(const RenderBox& renderBox)
{
    if (renderBox.isRenderView())
        return true;

    if (!renderBox.element())
        return false;

    // If there are any position:fixed inside of us, game over.
    if (auto* viewPositionedObjects = renderBox.view().positionedObjects()) {
        for (auto* positionedBox : *viewPositionedObjects) {
            if (positionedBox == &renderBox)
                continue;
            if (positionedBox->isFixedPositioned() && renderBox.element()->contains(positionedBox->element()))
                return false;
        }
    }

    if (renderBox.canContainAbsolutelyPositionedObjects()) {
        // Our layout overflow will include all descendant positioned elements.
        return true;
    }

    // This renderer may have positioned descendants whose containing block is some ancestor.
    if (auto* containingBlock = RenderObject::containingBlockForPositionType(PositionType::Absolute, renderBox)) {
        if (auto* positionedObjects = containingBlock->positionedObjects()) {
            for (auto* positionedBox : *positionedObjects) {
                if (positionedBox == &renderBox)
                    continue;
                if (renderBox.element()->contains(positionedBox->element()))
                    return false;
            }
        }
    }
    return false;
}

LayoutRect Element::absoluteEventBounds(bool& boundsIncludeAllDescendantElements, bool& includesFixedPositionElements)
{
    boundsIncludeAllDescendantElements = false;
    includesFixedPositionElements = false;

    if (!renderer())
        return LayoutRect();

    LayoutRect result;
    if (isSVGElement()) {
        // Get the bounding rectangle from the SVG model.
        SVGElement& svgElement = downcast<SVGElement>(*this);
        if (auto localRect = svgElement.getBoundingBox())
            result = LayoutRect(renderer()->localToAbsoluteQuad(*localRect, UseTransforms, &includesFixedPositionElements).boundingBox());
    } else {
        auto* renderer = this->renderer();
        if (is<RenderBox>(renderer)) {
            auto& box = downcast<RenderBox>(*renderer);

            bool computedBounds = false;
            
            if (RenderFragmentedFlow* fragmentedFlow = box.enclosingFragmentedFlow()) {
                bool wasFixed = false;
                Vector<FloatQuad> quads;
                if (fragmentedFlow->absoluteQuadsForBox(quads, &wasFixed, &box)) {
                    result = LayoutRect(unitedBoundingBoxes(quads));
                    computedBounds = true;
                } else {
                    // Probably columns. Just return the bounds of the multicol block for now.
                    // FIXME: this doesn't handle nested columns.
                    RenderElement* multicolContainer = fragmentedFlow->parent();
                    if (multicolContainer && is<RenderBox>(multicolContainer)) {
                        auto overflowRect = downcast<RenderBox>(*multicolContainer).layoutOverflowRect();
                        result = LayoutRect(multicolContainer->localToAbsoluteQuad(FloatRect(overflowRect), UseTransforms, &includesFixedPositionElements).boundingBox());
                        computedBounds = true;
                    }
                }
            }

            if (!computedBounds) {
                LayoutRect overflowRect = box.layoutOverflowRect();
                result = LayoutRect(box.localToAbsoluteQuad(FloatRect(overflowRect), UseTransforms, &includesFixedPositionElements).boundingBox());
                boundsIncludeAllDescendantElements = layoutOverflowRectContainsAllDescendants(box);
            }
        } else
            result = LayoutRect(renderer->absoluteBoundingBoxRect(true /* useTransforms */, &includesFixedPositionElements));
    }

    return result;
}

LayoutRect Element::absoluteEventBoundsOfElementAndDescendants(bool& includesFixedPositionElements)
{
    bool boundsIncludeDescendants;
    LayoutRect result = absoluteEventBounds(boundsIncludeDescendants, includesFixedPositionElements);
    if (boundsIncludeDescendants)
        return result;

    for (auto& child : childrenOfType<Element>(*this)) {
        bool includesFixedPosition = false;
        LayoutRect childBounds = child.absoluteEventBoundsOfElementAndDescendants(includesFixedPosition);
        includesFixedPositionElements |= includesFixedPosition;
        result.unite(childBounds);
    }

    return result;
}

LayoutRect Element::absoluteEventHandlerBounds(bool& includesFixedPositionElements)
{
    // This is not web-exposed, so don't call the FOUC-inducing updateLayoutIgnorePendingStylesheets().
    FrameView* frameView = document().view();
    if (!frameView)
        return LayoutRect();

    return absoluteEventBoundsOfElementAndDescendants(includesFixedPositionElements);
}

static std::optional<std::pair<RenderObject*, LayoutRect>> listBoxElementBoundingBox(const Element& element)
{
    HTMLSelectElement* selectElement;
    bool isGroup;
    if (is<HTMLOptionElement>(element)) {
        selectElement = downcast<HTMLOptionElement>(element).ownerSelectElement();
        isGroup = false;
    } else if (is<HTMLOptGroupElement>(element)) {
        selectElement = downcast<HTMLOptGroupElement>(element).ownerSelectElement();
        isGroup = true;
    } else
        return std::nullopt;

    if (!selectElement || !selectElement->renderer() || !is<RenderListBox>(selectElement->renderer()))
        return std::nullopt;

    auto& renderer = downcast<RenderListBox>(*selectElement->renderer());
    std::optional<LayoutRect> boundingBox;
    int optionIndex = 0;
    for (auto* item : selectElement->listItems()) {
        if (item == &element) {
            LayoutPoint additionOffset;
            boundingBox = renderer.itemBoundingBoxRect(additionOffset, optionIndex);
            if (!isGroup)
                break;
        } else if (isGroup && boundingBox) {
            if (item->parentNode() != &element)
                break;
            LayoutPoint additionOffset;
            boundingBox->setHeight(boundingBox->height() + renderer.itemBoundingBoxRect(additionOffset, optionIndex).height());
        }
        ++optionIndex;
    }

    if (!boundingBox)
        return std::nullopt;

    return std::pair<RenderObject*, LayoutRect> { &renderer, boundingBox.value() };
}

Ref<DOMRectList> Element::getClientRects()
{
    document().updateLayoutIgnorePendingStylesheets();

    RenderObject* renderer = this->renderer();
    Vector<FloatQuad> quads;

    if (auto pair = listBoxElementBoundingBox(*this)) {
        renderer = pair.value().first;
        quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
    } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
        renderBoxModelObject->absoluteQuads(quads);
    else if (isSVGElement() && renderer)
        renderer->absoluteQuads(quads);

    // FIXME: Handle table/inline-table with a caption.

    if (quads.isEmpty())
        return DOMRectList::create();

    document().convertAbsoluteToClientQuads(quads, renderer->style());
    return DOMRectList::create(quads);
}

std::optional<std::pair<RenderObject*, FloatRect>> Element::boundingAbsoluteRectWithoutLayout() const
{
    RenderObject* renderer = this->renderer();
    Vector<FloatQuad> quads;
    if (isSVGElement() && renderer && !renderer->isSVGRootOrLegacySVGRoot()) {
        // Get the bounding rectangle from the SVG model.
        if (auto localRect = downcast<SVGElement>(*this).getBoundingBox())
            quads.append(renderer->localToAbsoluteQuad(*localRect));
    } else if (auto pair = listBoxElementBoundingBox(*this)) {
        renderer = pair.value().first;
        quads.append(renderer->localToAbsoluteQuad(FloatQuad { pair.value().second }));
    } else if (auto* renderBoxModelObject = this->renderBoxModelObject())
        renderBoxModelObject->absoluteQuads(quads);

    if (quads.isEmpty())
        return std::nullopt;

    return std::make_pair(renderer, unitedBoundingBoxes(quads));
}

FloatRect Element::boundingClientRect()
{
    document().updateLayoutIgnorePendingStylesheets();
    auto pair = boundingAbsoluteRectWithoutLayout();
    if (!pair)
        return { };
    RenderObject* renderer = pair->first;
    FloatRect result = pair->second;
    document().convertAbsoluteToClientRect(result, renderer->style());
    return result;
}

Ref<DOMRect> Element::getBoundingClientRect()
{
    return DOMRect::create(boundingClientRect());
}
    
IntRect Element::screenRect() const
{
    if (RenderObject* renderer = this->renderer())
        return document().view()->contentsToScreen(renderer->absoluteBoundingBoxRect());
    return IntRect();
}

const AtomString& Element::getAttribute(const AtomString& qualifiedName) const
{
    if (!elementData() || qualifiedName.isEmpty())
        return nullAtom();
    synchronizeAttribute(qualifiedName);
    if (const Attribute* attribute = elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttributeCase(*this)))
        return attribute->value();
    return nullAtom();
}

const AtomString& Element::getAttributeNS(const AtomString& namespaceURI, const AtomString& localName) const
{
    return getAttribute(QualifiedName(nullAtom(), localName, namespaceURI));
}

// https://dom.spec.whatwg.org/#dom-element-toggleattribute
ExceptionOr<bool> Element::toggleAttribute(const AtomString& qualifiedName, std::optional<bool> force)
{
    if (!Document::isValidName(qualifiedName))
        return Exception { InvalidCharacterError };

    synchronizeAttribute(qualifiedName);

    auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
    unsigned index = elementData() ? elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false) : ElementData::attributeNotFound;
    if (index == ElementData::attributeNotFound) {
        if (!force || *force) {
            setAttributeInternal(index, QualifiedName { nullAtom(), caseAdjustedQualifiedName, nullAtom() }, emptyAtom(), NotInSynchronizationOfLazyAttribute);
            return true;
        }
        return false;
    }

    if (!force || !*force) {
        removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
        return false;
    }
    return true;
}

ExceptionOr<void> Element::setAttribute(const AtomString& qualifiedName, const AtomString& value)
{
    if (!Document::isValidName(qualifiedName))
        return Exception { InvalidCharacterError };

    synchronizeAttribute(qualifiedName);
    auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
    unsigned index = elementData() ? elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false) : ElementData::attributeNotFound;
    auto name = index != ElementData::attributeNotFound ? attributeAt(index).name() : QualifiedName { nullAtom(), caseAdjustedQualifiedName, nullAtom() };
    setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);

    return { };
}

void Element::setAttribute(const QualifiedName& name, const AtomString& value)
{
    synchronizeAttribute(name);
    unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
    setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
}

void Element::setAttributeWithoutSynchronization(const QualifiedName& name, const AtomString& value)
{
    unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
    setAttributeInternal(index, name, value, NotInSynchronizationOfLazyAttribute);
}

void Element::setSynchronizedLazyAttribute(const QualifiedName& name, const AtomString& value)
{
    unsigned index = elementData() ? elementData()->findAttributeIndexByName(name) : ElementData::attributeNotFound;
    setAttributeInternal(index, name, value, InSynchronizationOfLazyAttribute);
}

inline void Element::setAttributeInternal(unsigned index, const QualifiedName& name, const AtomString& newValue, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
{
    ASSERT_WITH_MESSAGE(refCount() || parentNode(), "Attribute must not be set on an element before adoptRef");

    if (newValue.isNull()) {
        if (index != ElementData::attributeNotFound)
            removeAttributeInternal(index, inSynchronizationOfLazyAttribute);
        return;
    }

    if (index == ElementData::attributeNotFound) {
        addAttributeInternal(name, newValue, inSynchronizationOfLazyAttribute);
        return;
    }

    if (inSynchronizationOfLazyAttribute) {
        ensureUniqueElementData().attributeAt(index).setValue(newValue);
        return;
    }

    const Attribute& attribute = attributeAt(index);
    QualifiedName attributeName = attribute.name();
    AtomString oldValue = attribute.value();

    willModifyAttribute(attributeName, oldValue, newValue);

    if (newValue != oldValue) {
        Style::AttributeChangeInvalidation styleInvalidation(*this, name, oldValue, newValue);
        ensureUniqueElementData().attributeAt(index).setValue(newValue);
    }

    didModifyAttribute(attributeName, oldValue, newValue);
}

static inline AtomString makeIdForStyleResolution(const AtomString& value, bool inQuirksMode)
{
    if (inQuirksMode)
        return value.convertToASCIILowercase();
    return value;
}

static inline bool isElementReflectionAttribute(const QualifiedName& name)
{
    return name == HTMLNames::aria_activedescendantAttr || name == HTMLNames::aria_errormessageAttr;
}

static inline bool isElementsArrayReflectionAttribute(const QualifiedName& name)
{
    return name == HTMLNames::aria_controlsAttr
        || name == HTMLNames::aria_describedbyAttr
        || name == HTMLNames::aria_detailsAttr
        || name == HTMLNames::aria_flowtoAttr
        || name == HTMLNames::aria_labelledbyAttr
        || name == HTMLNames::aria_ownsAttr;
}

void Element::attributeChanged(const QualifiedName& name, const AtomString& oldValue, const AtomString& newValue, AttributeModificationReason)
{
    bool valueIsSameAsBefore = oldValue == newValue;

    if (!valueIsSameAsBefore) {
        if (name == HTMLNames::accesskeyAttr)
            document().invalidateAccessKeyCache();
        else if (name == HTMLNames::classAttr)
            classAttributeChanged(newValue);
        else if (name == HTMLNames::idAttr) {
            AtomString oldId = elementData()->idForStyleResolution();
            AtomString newId = makeIdForStyleResolution(newValue, document().inQuirksMode());
            if (newId != oldId) {
                Style::IdChangeInvalidation styleInvalidation(*this, oldId, newId);
                elementData()->setIdForStyleResolution(newId);
            }

            if (!oldValue.isEmpty())
                treeScope().idTargetObserverRegistry().notifyObservers(*oldValue.impl());
            if (!newValue.isEmpty())
                treeScope().idTargetObserverRegistry().notifyObservers(*newValue.impl());
        } else if (name == HTMLNames::nameAttr)
            elementData()->setHasNameAttribute(!newValue.isNull());
        else if (name == HTMLNames::nonceAttr) {
            if (is<HTMLElement>(*this) || is<SVGElement>(*this))
                setNonce(newValue.isNull() ? emptyAtom() : newValue);
        } else if (name == HTMLNames::pseudoAttr) {
            if (needsStyleInvalidation() && isInShadowTree())
                invalidateStyleForSubtree();
        } else if (name == HTMLNames::slotAttr) {
            if (auto* parent = parentElement()) {
                if (auto* shadowRoot = parent->shadowRoot())
                    shadowRoot->hostChildElementDidChangeSlotAttribute(*this, oldValue, newValue);
            }
        } else if (name == HTMLNames::partAttr)
            partAttributeChanged(newValue);
        else if (document().settings().ariaReflectionForElementReferencesEnabled() && (isElementReflectionAttribute(name) || isElementsArrayReflectionAttribute(name))) {
            if (auto* map = explicitlySetAttrElementsMapIfExists())
                map->remove(name);
        } else if (name == HTMLNames::exportpartsAttr) {
            if (auto* shadowRoot = this->shadowRoot()) {
                shadowRoot->invalidatePartMappings();
                Style::Invalidator::invalidateShadowParts(*shadowRoot);
            }
        }
    }

    parseAttribute(name, newValue);

    document().incDOMTreeVersion();

    if (UNLIKELY(isDefinedCustomElement()))
        CustomElementReactionQueue::enqueueAttributeChangedCallbackIfNeeded(*this, name, oldValue, newValue);

    if (valueIsSameAsBefore)
        return;

    invalidateNodeListAndCollectionCachesInAncestorsForAttribute(name);

    if (AXObjectCache* cache = document().existingAXObjectCache())
        cache->deferAttributeChangeIfNeeded(name, this);
}

ExplicitlySetAttrElementsMap& Element::explicitlySetAttrElementsMap()
{
    return ensureElementRareData().explicitlySetAttrElementsMap();
}

ExplicitlySetAttrElementsMap* Element::explicitlySetAttrElementsMapIfExists() const
{
    return hasRareData() ? &elementRareData()->explicitlySetAttrElementsMap() : nullptr;
}

Element* Element::getElementAttribute(const QualifiedName& attributeName) const
{
    ASSERT(document().settings().ariaReflectionForElementReferencesEnabled());
    ASSERT(isElementReflectionAttribute(attributeName));

    if (auto* map = explicitlySetAttrElementsMapIfExists()) {
        auto it = map->find(attributeName);
        if (it != map->end()) {
            ASSERT(it->value.size() == 1);
            auto* element = it->value[0].get();
            if (element && isDescendantOrShadowDescendantOf(element->rootNode()))
                return element;
            return nullptr;
        }
    }

    auto id = getAttribute(attributeName);
    if (id.isNull())
        return nullptr;

    return treeScope().getElementById(id);
}

void Element::setElementAttribute(const QualifiedName& attributeName, Element* element)
{
    ASSERT(document().settings().ariaReflectionForElementReferencesEnabled());
    ASSERT(isElementReflectionAttribute(attributeName));

    if (!element) {
        if (auto* map = explicitlySetAttrElementsMapIfExists())
            map->remove(attributeName);
        removeAttribute(attributeName);
        return;
    }

    auto id = element->getIdAttribute();
    if (!id.isNull() && &rootNode() == &element->rootNode() && treeScope().getElementById(id) == element)
        setAttribute(attributeName, id);
    else
        setAttribute(attributeName, emptyAtom());

    explicitlySetAttrElementsMap().set(attributeName, Vector<WeakPtr<Element>> { element });
}

std::optional<Vector<RefPtr<Element>>> Element::getElementsArrayAttribute(const QualifiedName& attributeName) const
{
    ASSERT(document().settings().ariaReflectionForElementReferencesEnabled());
    ASSERT(isElementsArrayReflectionAttribute(attributeName));

    if (auto* map = explicitlySetAttrElementsMapIfExists()) {
        if (auto it = map->find(attributeName); it != map->end()) {
            return compactMap(it->value, [&](auto& element) -> std::optional<RefPtr<Element>> {
                if (element && isDescendantOrShadowDescendantOf(element->rootNode()))
                    return element.get();
                return std::nullopt;
            });
        }
    }

    auto attr = attributeName;
    if (attr == HTMLNames::aria_labelledbyAttr && !hasAttribute(HTMLNames::aria_labelledbyAttr) && hasAttribute(HTMLNames::aria_labeledbyAttr))
        attr = HTMLNames::aria_labeledbyAttr;

    if (!hasAttribute(attr))
        return std::nullopt;

    SpaceSplitString ids(getAttribute(attr), SpaceSplitString::ShouldFoldCase::No);
    Vector<RefPtr<Element>> elements;
    for (unsigned i = 0; i < ids.size(); ++i) {
        if (auto* element = treeScope().getElementById(ids[i]))
            elements.append(element);
    }
    return elements;
}

void Element::setElementsArrayAttribute(const QualifiedName& attributeName, std::optional<Vector<RefPtr<Element>>>&& elements)
{
    ASSERT(document().settings().ariaReflectionForElementReferencesEnabled());
    ASSERT(isElementsArrayReflectionAttribute(attributeName));

    if (!elements) {
        if (auto* map = explicitlySetAttrElementsMapIfExists())
            map->remove(attributeName);
        removeAttribute(attributeName);
        return;
    }

    Vector<WeakPtr<Element>> newElements;
    newElements.reserveInitialCapacity(elements->size());
    StringBuilder value;
    for (auto element : elements.value()) {
        newElements.uncheckedAppend(element);
        if (value.isEmpty() && newElements.size() > 1)
            continue;

        auto id = element->getIdAttribute();
        if (!id.isNull() && &rootNode() == &element->rootNode() && treeScope().getElementById(id) == element) {
            if (!value.isEmpty())
                value.append(' ');
            value.append(id);
        } else
            value.clear();
    }
    setAttribute(attributeName, value.toAtomString());

    explicitlySetAttrElementsMap().set(attributeName, WTFMove(newElements));
}

template <typename CharacterType>
static inline bool isNonEmptyTokenList(const CharacterType* characters, unsigned length)
{
    ASSERT(length > 0);

    unsigned i = 0;
    do {
        if (isNotHTMLSpace(characters[i]))
            break;
        ++i;
    } while (i < length);

    return i < length;
}

static inline bool isNonEmptyTokenList(const AtomString& stringValue)
{
    unsigned length = stringValue.length();

    if (!length)
        return false;

    if (stringValue.is8Bit())
        return isNonEmptyTokenList(stringValue.characters8(), length);
    return isNonEmptyTokenList(stringValue.characters16(), length);
}

void Element::classAttributeChanged(const AtomString& newClassString)
{
    // Note: We'll need ElementData, but it doesn't have to be UniqueElementData.
    if (!elementData())
        ensureUniqueElementData();

    auto shouldFoldCase = document().inQuirksMode() ? SpaceSplitString::ShouldFoldCase::Yes : SpaceSplitString::ShouldFoldCase::No;
    bool newStringHasClasses = isNonEmptyTokenList(newClassString);

    auto oldClassNames = elementData()->classNames();
    auto newClassNames = newStringHasClasses ? SpaceSplitString(newClassString, shouldFoldCase) : SpaceSplitString();
    {
        Style::ClassChangeInvalidation styleInvalidation(*this, oldClassNames, newClassNames);
        elementData()->setClassNames(WTFMove(newClassNames));
    }

    if (hasRareData()) {
        if (auto* classList = elementRareData()->classList())
            classList->associatedAttributeValueChanged(newClassString);
    }
}

void Element::partAttributeChanged(const AtomString& newValue)
{
    bool hasParts = isNonEmptyTokenList(newValue);
    if (hasParts || !partNames().isEmpty()) {
        auto newParts = hasParts ? SpaceSplitString(newValue, SpaceSplitString::ShouldFoldCase::No) : SpaceSplitString();
        ensureElementRareData().setPartNames(WTFMove(newParts));
    }

    if (hasRareData()) {
        if (auto* partList = elementRareData()->partList())
            partList->associatedAttributeValueChanged(newValue);
    }

    if (needsStyleInvalidation() && isInShadowTree())
        invalidateStyleInternal();
}

URL Element::absoluteLinkURL() const
{
    if (!isLink())
        return URL();

    AtomString linkAttribute;
    if (hasTagName(SVGNames::aTag))
        linkAttribute = getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
    else
        linkAttribute = getAttribute(HTMLNames::hrefAttr);

    if (linkAttribute.isEmpty())
        return URL();

    return document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkAttribute));
}

#if ENABLE(TOUCH_EVENTS)

bool Element::allowsDoubleTapGesture() const
{
    if (renderStyle() && renderStyle()->touchActions() != TouchAction::Auto)
        return false;

    Element* parent = parentElement();
    return !parent || parent->allowsDoubleTapGesture();
}

#endif

Style::Resolver& Element::styleResolver()
{
    if (auto* shadowRoot = containingShadowRoot())
        return shadowRoot->styleScope().resolver();

    return document().styleScope().resolver();
}

Style::ElementStyle Element::resolveStyle(const Style::ResolutionContext& resolutionContext)
{
    return styleResolver().styleForElement(*this, resolutionContext);
}

void invalidateForSiblingCombinators(Element* sibling)
{
    for (; sibling; sibling = sibling->nextElementSibling()) {
        if (sibling->styleIsAffectedByPreviousSibling())
            sibling->invalidateStyleInternal();
        if (sibling->descendantsAffectedByPreviousSibling()) {
            for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
                siblingChild->invalidateStyleForSubtreeInternal();
        }
        if (!sibling->affectsNextSiblingElementStyle())
            return;
    }
}

static void invalidateSiblingsIfNeeded(Element& element)
{
    if (!element.affectsNextSiblingElementStyle())
        return;
    auto* parent = element.parentElement();
    if (parent && parent->styleValidity() >= Style::Validity::SubtreeInvalid)
        return;

    invalidateForSiblingCombinators(element.nextElementSibling());
}

void Element::invalidateStyle()
{
    Node::invalidateStyle(Style::Validity::ElementInvalid);
    invalidateSiblingsIfNeeded(*this);
}

void Element::invalidateStyleAndLayerComposition()
{
    Node::invalidateStyle(Style::Validity::ElementInvalid, Style::InvalidationMode::RecompositeLayer);
    invalidateSiblingsIfNeeded(*this);
}

void Element::invalidateStyleForSubtree()
{
    Node::invalidateStyle(Style::Validity::SubtreeInvalid);
    invalidateSiblingsIfNeeded(*this);
}

void Element::invalidateStyleAndRenderersForSubtree()
{
    Node::invalidateStyle(Style::Validity::SubtreeAndRenderersInvalid);
    invalidateSiblingsIfNeeded(*this);
}

void Element::invalidateStyleInternal()
{
    Node::invalidateStyle(Style::Validity::ElementInvalid);
}

void Element::invalidateStyleForSubtreeInternal()
{
    Node::invalidateStyle(Style::Validity::SubtreeInvalid);
}

void Element::invalidateForQueryContainerSizeChange()
{
    // FIXME: Ideally we would just recompute things that are actually affected by containers queries within the subtree.
    Node::invalidateStyle(Style::Validity::SubtreeInvalid);
    setNodeFlag(NodeFlag::NeedsUpdateQueryContainerDependentStyle);
}

bool Element::needsUpdateQueryContainerDependentStyle() const
{
    return hasNodeFlag(NodeFlag::NeedsUpdateQueryContainerDependentStyle);
}

void Element::clearNeedsUpdateQueryContainerDependentStyle()
{
    clearNodeFlag(NodeFlag::NeedsUpdateQueryContainerDependentStyle);
}

void Element::invalidateEventListenerRegions()
{
    // Event listener region is updated via style update.
    invalidateStyleInternal();
}

bool Element::hasDisplayContents() const
{
    if (!hasRareData())
        return false;

    const RenderStyle* style = elementRareData()->computedStyle();
    return style && style->display() == DisplayType::Contents;
}

void Element::storeDisplayContentsStyle(std::unique_ptr<RenderStyle> style)
{
    ASSERT(style && style->display() == DisplayType::Contents);
    ASSERT(!renderer() || isPseudoElement());
    ensureElementRareData().setComputedStyle(WTFMove(style));
    clearNodeFlag(NodeFlag::IsComputedStyleInvalidFlag);
}

// Returns true is the given attribute is an event handler.
// We consider an event handler any attribute that begins with "on".
// It is a simple solution that has the advantage of not requiring any
// code or configuration change if a new event handler is defined.

bool Element::isEventHandlerAttribute(const Attribute& attribute) const
{
    return attribute.name().namespaceURI().isNull() && attribute.name().localName().startsWith("on"_s);
}

bool Element::attributeContainsJavaScriptURL(const Attribute& attribute) const
{
    return isURLAttribute(attribute) && WTF::protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(attribute.value()));
}

void Element::stripScriptingAttributes(Vector<Attribute>& attributeVector) const
{
    attributeVector.removeAllMatching([this](auto& attribute) -> bool {
        return this->isEventHandlerAttribute(attribute)
            || this->attributeContainsJavaScriptURL(attribute)
            || this->isHTMLContentAttribute(attribute);
    });
}

void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
{
    ASSERT(!isConnected());
    ASSERT(!parentNode());
    ASSERT(!m_elementData);

    if (!attributeVector.isEmpty()) {
        if (document().sharedObjectPool())
            m_elementData = document().sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector);
        else
            m_elementData = ShareableElementData::createWithAttributes(attributeVector);

    }

    parserDidSetAttributes();

    // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData.
    for (const auto& attribute : attributeVector)
        attributeChanged(attribute.name(), nullAtom(), attribute.value(), ModifiedDirectly);
}

void Element::parserDidSetAttributes()
{
}

void Element::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
{
    ASSERT_WITH_SECURITY_IMPLICATION(&document() == &newDocument);

    if (oldDocument.inQuirksMode() != document().inQuirksMode()) {
        // ElementData::m_classNames or ElementData::m_idForStyleResolution need to be updated with the right case.
        if (hasID())
            attributeChanged(idAttr, nullAtom(), getIdAttribute());
        if (hasClass())
            attributeChanged(classAttr, nullAtom(), getAttribute(classAttr));
    }

    if (UNLIKELY(isDefinedCustomElement()))
        CustomElementReactionQueue::enqueueAdoptedCallbackIfNeeded(*this, oldDocument, newDocument);

    if (auto* observerData = intersectionObserverDataIfExists()) {
        for (const auto& observer : observerData->observers) {
            if (observer->hasObservationTargets()) {
                oldDocument.removeIntersectionObserver(*observer);
                newDocument.addIntersectionObserver(*observer);
            }
        }
    }
}

bool Element::hasAttributes() const
{
    synchronizeAllAttributes();
    return elementData() && elementData()->length();
}

bool Element::hasEquivalentAttributes(const Element& other) const
{
    synchronizeAllAttributes();
    other.synchronizeAllAttributes();
    if (elementData() == other.elementData())
        return true;
    if (elementData())
        return elementData()->isEquivalent(other.elementData());
    if (other.elementData())
        return other.elementData()->isEquivalent(elementData());
    return true;
}

String Element::nodeName() const
{
    return m_tagName.toString();
}

String Element::nodeNamePreservingCase() const
{
    return m_tagName.toString();
}

ExceptionOr<void> Element::setPrefix(const AtomString& prefix)
{
    auto result = checkSetPrefix(prefix);
    if (result.hasException())
        return result.releaseException();

    m_tagName.setPrefix(prefix.isEmpty() ? nullAtom() : prefix);
    return { };
}

const AtomString& Element::imageSourceURL() const
{
    return attributeWithoutSynchronization(srcAttr);
}

bool Element::rendererIsNeeded(const RenderStyle& style)
{
    return rendererIsEverNeeded() && style.display() != DisplayType::None && style.display() != DisplayType::Contents;
}

RenderPtr<RenderElement> Element::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
{
    return RenderElement::createFor(*this, WTFMove(style));
}

Node::InsertedIntoAncestorResult Element::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
{
    ContainerNode::insertedIntoAncestor(insertionType, parentOfInsertedTree);

#if ENABLE(FULLSCREEN_API)
    if (containsFullScreenElement() && parentElement() && !parentElement()->containsFullScreenElement())
        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true);
#endif

    if (parentNode() == &parentOfInsertedTree) {
        if (auto* shadowRoot = parentNode()->shadowRoot())
            shadowRoot->hostChildElementDidChange(*this);
    }

    if (!parentOfInsertedTree.isInTreeScope())
        return InsertedIntoAncestorResult::Done;

    bool becomeConnected = insertionType.connectedToDocument;
    TreeScope* newScope = &parentOfInsertedTree.treeScope();
    auto* newDocument = becomeConnected ? dynamicDowncast<HTMLDocument>(newScope->documentScope()) : nullptr;
    if (!insertionType.treeScopeChanged)
        newScope = nullptr;

    const AtomString& idValue = getIdAttribute();
    if (!idValue.isNull()) {
        if (newScope)
            updateIdForTreeScope(*newScope, nullAtom(), idValue);
        if (newDocument)
            updateIdForDocument(*newDocument, nullAtom(), idValue, AlwaysUpdateHTMLDocumentNamedItemMaps);
    }

    const AtomString& nameValue = getNameAttribute();
    if (!nameValue.isNull()) {
        if (newScope)
            updateNameForTreeScope(*newScope, nullAtom(), nameValue);
        if (newDocument)
            updateNameForDocument(*newDocument, nullAtom(), nameValue);
    }

    if (becomeConnected) {
        if (UNLIKELY(isCustomElementUpgradeCandidate())) {
            ASSERT(isConnected());
            CustomElementReactionQueue::tryToUpgradeElement(*this);
        }
        if (UNLIKELY(isDefinedCustomElement()))
            CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this);
    }

    if (shouldAutofocus(*this))
        document().topDocument().appendAutofocusCandidate(*this);

    return InsertedIntoAncestorResult::Done;
}

void Element::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
{
#if ENABLE(FULLSCREEN_API)
    if (containsFullScreenElement())
        setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
#endif

    if (auto* page = document().page()) {
#if ENABLE(POINTER_LOCK)
        page->pointerLockController().elementWasRemoved(*this);
#endif
        page->pointerCaptureController().elementWasRemoved(*this);
    }

    setSavedLayerScrollPosition(ScrollPosition());

    if (oldParentOfRemovedTree.isInTreeScope()) {
        TreeScope* oldScope = &oldParentOfRemovedTree.treeScope();
        Document* oldDocument = removalType.disconnectedFromDocument ? &oldScope->documentScope() : nullptr;
        auto* oldHTMLDocument = dynamicDowncast<HTMLDocument>(oldDocument);
        if (!removalType.treeScopeChanged)
            oldScope = nullptr;

        const AtomString& idValue = getIdAttribute();
        if (!idValue.isNull()) {
            if (oldScope)
                updateIdForTreeScope(*oldScope, idValue, nullAtom());
            if (oldHTMLDocument)
                updateIdForDocument(*oldHTMLDocument, idValue, nullAtom(), AlwaysUpdateHTMLDocumentNamedItemMaps);
        }

        const AtomString& nameValue = getNameAttribute();
        if (!nameValue.isNull()) {
            if (oldScope)
                updateNameForTreeScope(*oldScope, nameValue, nullAtom());
            if (oldHTMLDocument)
                updateNameForDocument(*oldHTMLDocument, nameValue, nullAtom());
        }

        if (oldDocument) {
            if (oldDocument->cssTarget() == this)
                oldDocument->setCSSTarget(nullptr);
        }

        if (removalType.disconnectedFromDocument && UNLIKELY(isDefinedCustomElement()))
            CustomElementReactionQueue::enqueueDisconnectedCallbackIfNeeded(*this);
    }

    if (!parentNode()) {
        if (auto* shadowRoot = oldParentOfRemovedTree.shadowRoot())
            shadowRoot->hostChildElementDidChange(*this);
    }

    clearBeforePseudoElement();
    clearAfterPseudoElement();

    ContainerNode::removedFromAncestor(removalType, oldParentOfRemovedTree);

    if (hasPendingResources())
        document().accessSVGExtensions().removeElementFromPendingResources(*this);

    Styleable::fromElement(*this).elementWasRemoved();

#if ENABLE(WHEEL_EVENT_LATCHING)
    if (RefPtr frame = document().frame(); frame && frame->page()) {
        if (auto* scrollLatchingController = frame->page()->scrollLatchingControllerIfExists())
            scrollLatchingController->removeLatchingStateForTarget(*this);
    }
#endif

    if (UNLIKELY(isInTopLayer()))
        removeFromTopLayer();
}

void Element::addShadowRoot(Ref<ShadowRoot>&& newShadowRoot)
{
    ASSERT(!newShadowRoot->hasChildNodes());
    ASSERT(!shadowRoot());

    ShadowRoot& shadowRoot = newShadowRoot;
    {
        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
        if (renderer() || hasDisplayContents())
            RenderTreeUpdater::tearDownRenderers(*this);

        ensureElementRareData().setShadowRoot(WTFMove(newShadowRoot));

        shadowRoot.setHost(*this);
        shadowRoot.setParentTreeScope(treeScope());

        NodeVector postInsertionNotificationTargets;
        notifyChildNodeInserted(*this, shadowRoot, postInsertionNotificationTargets);
        ASSERT_UNUSED(postInsertionNotificationTargets, postInsertionNotificationTargets.isEmpty());

        InspectorInstrumentation::didPushShadowRoot(*this, shadowRoot);

        invalidateStyleAndRenderersForSubtree();
    }

    if (shadowRoot.mode() == ShadowRootMode::UserAgent)
        didAddUserAgentShadowRoot(shadowRoot);
}

void Element::removeShadowRoot()
{
    RefPtr<ShadowRoot> oldRoot = shadowRoot();
    if (!oldRoot)
        return;

    InspectorInstrumentation::willPopShadowRoot(*this, *oldRoot);
    document().adjustFocusedNodeOnNodeRemoval(*oldRoot);

    ASSERT(!oldRoot->renderer());

    elementRareData()->clearShadowRoot();

    oldRoot->setHost(nullptr);
    oldRoot->setParentTreeScope(document());
}

static bool canAttachAuthorShadowRoot(const Element& element)
{
    static NeverDestroyed tagNames = [] {
        static constexpr std::array tagList {
            &articleTag,
            &asideTag,
            &blockquoteTag,
            &bodyTag,
            &divTag,
            &footerTag,
            &h1Tag,
            &h2Tag,
            &h3Tag,
            &h4Tag,
            &h5Tag,
            &h6Tag,
            &headerTag,
            &mainTag,
            &navTag,
            &pTag,
            &sectionTag,
            &spanTag
        };
        MemoryCompactLookupOnlyRobinHoodHashSet<AtomString> set;
        set.reserveInitialCapacity(sizeof(tagList));
        for (auto& name : tagList)
            set.add(name->get().localName());
        return set;
    }();

    if (!is<HTMLElement>(element))
        return false;

    const auto& localName = element.localName();
    if (tagNames.get().contains(localName))
        return true;

    if (Document::validateCustomElementName(localName) == CustomElementNameValidationStatus::Valid) {
        if (auto* window = element.document().domWindow()) {
            auto* registry = window->customElementRegistry();
            if (registry && registry->isShadowDisabled(localName))
                return false;
        }

        return true;
    }

    return false;
}

ExceptionOr<ShadowRoot&> Element::attachShadow(const ShadowRootInit& init)
{
    if (!canAttachAuthorShadowRoot(*this))
        return Exception { NotSupportedError };
    if (shadowRoot())
        return Exception { NotSupportedError };
    if (init.mode == ShadowRootMode::UserAgent)
        return Exception { TypeError };
    auto shadow = ShadowRoot::create(document(), init.mode, init.delegatesFocus ? ShadowRoot::DelegatesFocus::Yes : ShadowRoot::DelegatesFocus::No);
    auto& result = shadow.get();
    addShadowRoot(WTFMove(shadow));
    return result;
}

ShadowRoot* Element::shadowRootForBindings(JSC::JSGlobalObject& lexicalGlobalObject) const
{
    auto* shadow = shadowRoot();
    if (!shadow)
        return nullptr;
    if (shadow->mode() == ShadowRootMode::Open)
        return shadow;
    if (JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject)->world().shadowRootIsAlwaysOpen())
        return shadow;
    return nullptr;
}

RefPtr<ShadowRoot> Element::userAgentShadowRoot() const
{
    ASSERT(!shadowRoot() || shadowRoot()->mode() == ShadowRootMode::UserAgent);
    return shadowRoot();
}

ShadowRoot& Element::ensureUserAgentShadowRoot()
{
    if (auto shadow = userAgentShadowRoot())
        return *shadow;
    return createUserAgentShadowRoot();
}

ShadowRoot& Element::createUserAgentShadowRoot()
{
    ASSERT(!userAgentShadowRoot());
    auto newShadow = ShadowRoot::create(document(), ShadowRootMode::UserAgent);
    ShadowRoot& shadow = newShadow;
    addShadowRoot(WTFMove(newShadow));
    return shadow;
}

inline void Node::setCustomElementState(CustomElementState state)
{
    auto bitfields = rareDataBitfields();
    bitfields.customElementState = static_cast<uint16_t>(state);
    setRareDataBitfields(bitfields);
}

void Element::setIsDefinedCustomElement(JSCustomElementInterface& elementInterface)
{
    setCustomElementState(CustomElementState::Custom);
    auto& data = ensureElementRareData();
    if (!data.customElementReactionQueue())
        data.setCustomElementReactionQueue(makeUnique<CustomElementReactionQueue>(elementInterface));
    invalidateStyleForSubtree();
    InspectorInstrumentation::didChangeCustomElementState(*this);
}

void Element::setIsFailedCustomElement()
{
    setIsFailedCustomElementWithoutClearingReactionQueue();
    clearReactionQueueFromFailedCustomElement();
}

void Element::setIsFailedCustomElementWithoutClearingReactionQueue()
{
    ASSERT(isUndefinedCustomElement());
    ASSERT(customElementState() == CustomElementState::Undefined);
    setCustomElementState(CustomElementState::Failed);
    InspectorInstrumentation::didChangeCustomElementState(*this);
}

void Element::clearReactionQueueFromFailedCustomElement()
{
    ASSERT(isFailedCustomElement());
    if (hasRareData()) {
        // Clear the queue instead of deleting it since this function can be called inside CustomElementReactionQueue::invokeAll during upgrades.
        if (auto* queue = elementRareData()->customElementReactionQueue())
            queue->clear();
    }
}

void Element::setIsCustomElementUpgradeCandidate()
{
    ASSERT(customElementState() == CustomElementState::Uncustomized);
    setCustomElementState(CustomElementState::Undefined);
    InspectorInstrumentation::didChangeCustomElementState(*this);
}

void Element::enqueueToUpgrade(JSCustomElementInterface& elementInterface)
{
    ASSERT(isCustomElementUpgradeCandidate());
    ASSERT(!isDefinedCustomElement() && !isFailedCustomElement());
    auto& data = ensureElementRareData();
    bool alreadyScheduledToUpgrade = data.customElementReactionQueue();
    if (!alreadyScheduledToUpgrade)
        data.setCustomElementReactionQueue(makeUnique<CustomElementReactionQueue>(elementInterface));
    data.customElementReactionQueue()->enqueueElementUpgrade(*this, alreadyScheduledToUpgrade);
}

CustomElementReactionQueue* Element::reactionQueue() const
{
#if ASSERT_ENABLED
    if (isFailedCustomElement()) {
        auto* queue = elementRareData()->customElementReactionQueue();
        ASSERT(queue);
        ASSERT(queue->isEmpty() || queue->hasJustUpgradeReaction());
    } else
        ASSERT(isDefinedCustomElement() || isCustomElementUpgradeCandidate());
#endif
    if (!hasRareData())
        return nullptr;
    return elementRareData()->customElementReactionQueue();
}

const AtomString& Element::shadowPseudoId() const
{
    return pseudo();
}

bool Element::childTypeAllowed(NodeType type) const
{
    switch (type) {
    case ELEMENT_NODE:
    case TEXT_NODE:
    case COMMENT_NODE:
    case PROCESSING_INSTRUCTION_NODE:
    case CDATA_SECTION_NODE:
        return true;
    default:
        break;
    }
    return false;
}
void Element::childrenChanged(const ChildChange& change)
{
    ContainerNode::childrenChanged(change);

    if (auto* shadowRoot = this->shadowRoot()) {
        switch (change.type) {
        case ChildChange::Type::ElementInserted:
        case ChildChange::Type::ElementRemoved:
            // For elements, we notify shadowRoot in Element::insertedIntoAncestor and Element::removedFromAncestor.
            break;
        case ChildChange::Type::AllChildrenRemoved:
        case ChildChange::Type::AllChildrenReplaced:
            shadowRoot->didRemoveAllChildrenOfShadowHost();
            break;
        case ChildChange::Type::TextInserted:
        case ChildChange::Type::TextRemoved:
        case ChildChange::Type::TextChanged:
            shadowRoot->didChangeDefaultSlot();
            break;
        case ChildChange::Type::NonContentsChildInserted:
        case ChildChange::Type::NonContentsChildRemoved:
            break;
        }
    }
}

void Element::setAttributeEventListener(const AtomString& eventType, const QualifiedName& attributeName, const AtomString& attributeValue)
{
    setAttributeEventListener(eventType, JSLazyEventListener::create(*this, attributeName, attributeValue), mainThreadNormalWorld());
}

void Element::removeAllEventListeners()
{
    ContainerNode::removeAllEventListeners();
    if (ShadowRoot* shadowRoot = this->shadowRoot())
        shadowRoot->removeAllEventListeners();
}

void Element::beginParsingChildren()
{
    clearIsParsingChildrenFinished();
}

void Element::finishParsingChildren()
{
    ContainerNode::finishParsingChildren();
    setIsParsingChildrenFinished();

    Style::ChildChangeInvalidation::invalidateAfterFinishedParsingChildren(*this);
}

static void appendAttributes(StringBuilder& builder, const Element& element)
{
    if (element.hasID())
        builder.append(" id=\'", element.getIdAttribute(), '\'');

    if (element.hasClass()) {
        builder.append(" class=\'");
        size_t classNamesToDump = element.classNames().size();
        constexpr size_t maxNumClassNames = 7;
        bool addEllipsis = false;
        if (classNamesToDump > maxNumClassNames) {
            classNamesToDump = maxNumClassNames;
            addEllipsis = true;
        }
        
        for (size_t i = 0; i < classNamesToDump; ++i) {
            if (i > 0)
                builder.append(' ');
            builder.append(element.classNames()[i]);
        }
        if (addEllipsis)
            builder.append(" ...");
        builder.append('\'');
    }
}

String Element::description() const
{
    StringBuilder builder;

    builder.append(ContainerNode::description());
    appendAttributes(builder, *this);

    return builder.toString();
}

String Element::debugDescription() const
{
    StringBuilder builder;

    builder.append(ContainerNode::debugDescription());
    appendAttributes(builder, *this);

    return builder.toString();
}

const Vector<RefPtr<Attr>>& Element::attrNodeList()
{
    ASSERT(hasSyntheticAttrChildNodes());
    return *attrNodeListForElement(*this);
}

void Element::attachAttributeNodeIfNeeded(Attr& attrNode)
{
    ASSERT(!attrNode.ownerElement() || attrNode.ownerElement() == this);
    if (attrNode.ownerElement() == this)
        return;

    ScriptDisallowedScope::InMainThread scriptDisallowedScope;

    attrNode.attachToElement(*this);
    ensureAttrNodeListForElement(*this).append(&attrNode);
}

ExceptionOr<RefPtr<Attr>> Element::setAttributeNode(Attr& attrNode)
{
    RefPtr<Attr> oldAttrNode = attrIfExists(attrNode.localName(), shouldIgnoreAttributeCase(*this));
    if (oldAttrNode.get() == &attrNode)
        return oldAttrNode;

    // InUseAttributeError: Raised if node is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if (attrNode.ownerElement() && attrNode.ownerElement() != this)
        return Exception { InUseAttributeError };

    {
        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
        synchronizeAllAttributes();
    }

    auto& elementData = ensureUniqueElementData();

    auto existingAttributeIndex = elementData.findAttributeIndexByName(attrNode.localName(), shouldIgnoreAttributeCase(*this));

    // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value
    // before making changes to attrNode's Element connections.
    auto attrNodeValue = attrNode.value();

    if (existingAttributeIndex == ElementData::attributeNotFound) {
        attachAttributeNodeIfNeeded(attrNode);
        setAttributeInternal(elementData.findAttributeIndexByName(attrNode.qualifiedName()), attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
    } else {
        const Attribute& attribute = attributeAt(existingAttributeIndex);
        if (oldAttrNode)
            detachAttrNodeFromElementWithValue(oldAttrNode.get(), attribute.value());
        else
            oldAttrNode = Attr::create(document(), attrNode.qualifiedName(), attribute.value());

        attachAttributeNodeIfNeeded(attrNode);

        if (attribute.name().matches(attrNode.qualifiedName()))
            setAttributeInternal(existingAttributeIndex, attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
        else {
            removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute);
            setAttributeInternal(ensureUniqueElementData().findAttributeIndexByName(attrNode.qualifiedName()), attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);
        }
    }

    return oldAttrNode;
}

ExceptionOr<RefPtr<Attr>> Element::setAttributeNodeNS(Attr& attrNode)
{
    RefPtr<Attr> oldAttrNode = attrIfExists(attrNode.qualifiedName());
    if (oldAttrNode.get() == &attrNode)
        return oldAttrNode;

    // InUseAttributeError: Raised if node is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if (attrNode.ownerElement() && attrNode.ownerElement() != this)
        return Exception { InUseAttributeError };

    // Attr::value() will return its 'm_standaloneValue' member any time its Element is set to nullptr. We need to cache this value
    // before making changes to attrNode's Element connections.
    auto attrNodeValue = attrNode.value();
    unsigned index = 0;
    {
        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
        synchronizeAllAttributes();
        auto& elementData = ensureUniqueElementData();

        index = elementData.findAttributeIndexByName(attrNode.qualifiedName());

        if (index != ElementData::attributeNotFound) {
            if (oldAttrNode)
                detachAttrNodeFromElementWithValue(oldAttrNode.get(), elementData.attributeAt(index).value());
            else
                oldAttrNode = Attr::create(document(), attrNode.qualifiedName(), elementData.attributeAt(index).value());
        }
    }

    attachAttributeNodeIfNeeded(attrNode);
    setAttributeInternal(index, attrNode.qualifiedName(), attrNodeValue, NotInSynchronizationOfLazyAttribute);

    return oldAttrNode;
}

ExceptionOr<Ref<Attr>> Element::removeAttributeNode(Attr& attr)
{
    if (attr.ownerElement() != this)
        return Exception { NotFoundError };

    ASSERT(&document() == &attr.document());

    synchronizeAllAttributes();

    if (!m_elementData)
        return Exception { NotFoundError };

    auto existingAttributeIndex = m_elementData->findAttributeIndexByName(attr.qualifiedName());
    if (existingAttributeIndex == ElementData::attributeNotFound)
        return Exception { NotFoundError };

    Ref<Attr> oldAttrNode { attr };

    detachAttrNodeFromElementWithValue(&attr, m_elementData->attributeAt(existingAttributeIndex).value());
    removeAttributeInternal(existingAttributeIndex, NotInSynchronizationOfLazyAttribute);

    return oldAttrNode;
}

ExceptionOr<QualifiedName> Element::parseAttributeName(const AtomString& namespaceURI, const AtomString& qualifiedName)
{
    auto parseResult = Document::parseQualifiedName(namespaceURI, qualifiedName);
    if (parseResult.hasException())
        return parseResult.releaseException();
    QualifiedName parsedAttributeName { parseResult.releaseReturnValue() };
    if (!Document::hasValidNamespaceForAttributes(parsedAttributeName))
        return Exception { NamespaceError };
    return parsedAttributeName;
}

ExceptionOr<void> Element::setAttributeNS(const AtomString& namespaceURI, const AtomString& qualifiedName, const AtomString& value)
{
    auto result = parseAttributeName(namespaceURI, qualifiedName);
    if (result.hasException())
        return result.releaseException();
    setAttribute(result.releaseReturnValue(), value);
    return { };
}

void Element::removeAttributeInternal(unsigned index, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
{
    ASSERT_WITH_SECURITY_IMPLICATION(index < attributeCount());

    UniqueElementData& elementData = ensureUniqueElementData();

    QualifiedName name = elementData.attributeAt(index).name();
    AtomString valueBeingRemoved = elementData.attributeAt(index).value();

    if (RefPtr<Attr> attrNode = attrIfExists(name))
        detachAttrNodeFromElementWithValue(attrNode.get(), elementData.attributeAt(index).value());

    if (inSynchronizationOfLazyAttribute) {
        elementData.removeAttribute(index);
        return;
    }

    ASSERT(!valueBeingRemoved.isNull());
    willModifyAttribute(name, valueBeingRemoved, nullAtom());
    {
        Style::AttributeChangeInvalidation styleInvalidation(*this, name, valueBeingRemoved, nullAtom());
        elementData.removeAttribute(index);
    }

    didRemoveAttribute(name, valueBeingRemoved);
}

void Element::addAttributeInternal(const QualifiedName& name, const AtomString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
{
    if (inSynchronizationOfLazyAttribute) {
        ensureUniqueElementData().addAttribute(name, value);
        return;
    }

    willModifyAttribute(name, nullAtom(), value);
    {
        Style::AttributeChangeInvalidation styleInvalidation(*this, name, nullAtom(), value);
        ensureUniqueElementData().addAttribute(name, value);
    }
    didAddAttribute(name, value);
}

bool Element::removeAttribute(const AtomString& qualifiedName)
{
    if (!elementData())
        return false;

    AtomString caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
    unsigned index = elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false);
    if (index == ElementData::attributeNotFound) {
        if (UNLIKELY(caseAdjustedQualifiedName == styleAttr) && elementData()->styleAttributeIsDirty() && is<StyledElement>(*this))
            downcast<StyledElement>(*this).removeAllInlineStyleProperties();
        return false;
    }

    removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
    return true;
}

bool Element::removeAttributeNS(const AtomString& namespaceURI, const AtomString& localName)
{
    return removeAttribute(QualifiedName(nullAtom(), localName, namespaceURI));
}

RefPtr<Attr> Element::getAttributeNode(const AtomString& qualifiedName)
{
    if (!elementData())
        return nullptr;
    synchronizeAttribute(qualifiedName);
    const Attribute* attribute = elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttributeCase(*this));
    if (!attribute)
        return nullptr;
    return ensureAttr(attribute->name());
}

RefPtr<Attr> Element::getAttributeNodeNS(const AtomString& namespaceURI, const AtomString& localName)
{
    if (!elementData())
        return nullptr;
    QualifiedName qName(nullAtom(), localName, namespaceURI);
    synchronizeAttribute(qName);
    const Attribute* attribute = elementData()->findAttributeByName(qName);
    if (!attribute)
        return nullptr;
    return ensureAttr(attribute->name());
}

bool Element::hasAttribute(const AtomString& qualifiedName) const
{
    if (!elementData())
        return false;
    synchronizeAttribute(qualifiedName);
    return elementData()->findAttributeByName(qualifiedName, shouldIgnoreAttributeCase(*this));
}

bool Element::hasAttributeNS(const AtomString& namespaceURI, const AtomString& localName) const
{
    if (!elementData())
        return false;
    QualifiedName qName(nullAtom(), localName, namespaceURI);
    synchronizeAttribute(qName);
    return elementData()->findAttributeByName(qName);
}

static RefPtr<ShadowRoot> shadowRootWithDelegatesFocus(const Element& element)
{
    if (auto* root = element.shadowRoot()) {
        if (root->delegatesFocus())
            return root;
    }
    return nullptr;
}

static bool isProgramaticallyFocusable(Element& element)
{
    ScriptDisallowedScope::InMainThread scriptDisallowedScope;

    if (shadowRootWithDelegatesFocus(element))
        return false;

    // If the stylesheets have already been loaded we can reliably check isFocusable.
    // If not, we continue and set the focused node on the focus controller below so that it can be updated soon after attach.
    if (element.document().haveStylesheetsLoaded()) {
        if (!element.isFocusable())
            return false;
    }
    return element.supportsFocus();
}

static RefPtr<Element> findFirstProgramaticallyFocusableElementInComposedTree(Element& host)
{
    ASSERT(host.shadowRoot());
    for (auto& node : composedTreeDescendants(host)) {
        if (!is<Element>(node))
            continue;
        auto& element = downcast<Element>(node);
        if (isProgramaticallyFocusable(element))
            return &element;
    }
    return nullptr;
}

void Element::focus(const FocusOptions& options)
{
    if (!isConnected())
        return;

    Ref document { this->document() };
    if (document->focusedElement() == this) {
        if (document->page())
            document->page()->chrome().client().elementDidRefocus(*this, options);
        return;
    }

    RefPtr<Element> newTarget = this;

    // If we don't have renderer yet, isFocusable will compute it without style update.
    // FIXME: Expand it to avoid style update in all cases.
    if (renderer() && document->haveStylesheetsLoaded())
        document->updateStyleIfNeeded();

    if (&newTarget->document() != document.ptr())
        return;

    if (auto root = shadowRootWithDelegatesFocus(*this)) {
        RefPtr currentlyFocusedElement = document->focusedElement();
        if (root->containsIncludingShadowDOM(currentlyFocusedElement.get())) {
            if (document->page())
                document->page()->chrome().client().elementDidRefocus(*currentlyFocusedElement, options);
            return;
        }

        newTarget = findFirstProgramaticallyFocusableElementInComposedTree(*this);            
        if (!newTarget)
            return;
    } else if (!isProgramaticallyFocusable(*newTarget))
        return;

    if (Page* page = document->page()) {
        auto& frame = *document->frame();
        if (!frame.hasHadUserInteraction() && !frame.isMainFrame() && !document->topOrigin().isSameOriginDomain(document->securityOrigin()))
            return;

        FocusOptions optionsWithVisibility = options;
        if (options.trigger == FocusTrigger::Bindings && document->wasLastFocusByClick())
            optionsWithVisibility.visibility = FocusVisibility::Invisible;
        else if (options.trigger != FocusTrigger::Click)
            optionsWithVisibility.visibility = FocusVisibility::Visible;

        // Focus and change event handlers can cause us to lose our last ref.
        // If a focus event handler changes the focus to a different node it
        // does not make sense to continue and update appearence.
        if (!CheckedRef(page->focusController())->setFocusedElement(newTarget.get(), *document->frame(), optionsWithVisibility))
            return;
    }

    newTarget->findTargetAndUpdateFocusAppearance(options.selectionRestorationMode, options.preventScroll ? SelectionRevealMode::DoNotReveal : SelectionRevealMode::Reveal);
}

void Element::focusForBindings(FocusOptions&& options)
{
    options.trigger = FocusTrigger::Bindings;
    focus(WTFMove(options));
}

void Element::findTargetAndUpdateFocusAppearance(SelectionRestorationMode selectionMode, SelectionRevealMode revealMode)
{
#if PLATFORM(IOS_FAMILY)
    // Focusing a form element triggers animation in UIKit to scroll to the right position.
    // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(),
    // which would jump us around during this animation. See <rdar://problem/6699741>.
    if (revealMode == SelectionRevealMode::Reveal && is<HTMLFormControlElement>(*this))
        revealMode = SelectionRevealMode::RevealUpToMainFrame;
#endif

    auto target = focusAppearanceUpdateTarget();
    if (!target)
        return;

    target->updateFocusAppearance(selectionMode, revealMode);
}

// https://html.spec.whatwg.org/#focus-processing-model
RefPtr<Element> Element::focusAppearanceUpdateTarget()
{
    return this;
}

void Element::updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode revealMode)
{
    if (isRootEditableElement()) {
        // Keep frame alive in this method, since setSelection() may release the last reference to |frame|.
        RefPtr<Frame> frame = document().frame();
        if (!frame)
            return;
        
        // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
        if (this == frame->selection().selection().rootEditableElement())
            return;

        // FIXME: We should restore the previous selection if there is one.
        VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this));
        
        if (frame->selection().shouldChangeSelection(newSelection)) {
            frame->selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(), Element::defaultFocusTextStateChangeIntent());
            frame->selection().revealSelection(revealMode);
            return;
        }
    }

    if (RefPtr<FrameView> view = document().view())
        view->scheduleScrollToFocusedElement(revealMode);
}

void Element::blur()
{
    if (treeScope().focusedElementInScope() == this) {
        if (RefPtr frame = document().frame())
            CheckedRef(frame->page()->focusController())->setFocusedElement(nullptr, *frame);
        else
            document().setFocusedElement(nullptr);
    }
}

void Element::runFocusingStepsForAutofocus()
{
    focus();
}

void Element::dispatchFocusInEventIfNeeded(RefPtr<Element>&& oldFocusedElement)
{
    if (!document().hasListenerType(Document::FOCUSIN_LISTENER))
        return;
    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed() || !isInWebProcess());
    dispatchScopedEvent(FocusEvent::create(eventNames().focusinEvent, Event::CanBubble::Yes, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(oldFocusedElement)));
}

void Element::dispatchFocusOutEventIfNeeded(RefPtr<Element>&& newFocusedElement)
{
    if (!document().hasListenerType(Document::FOCUSOUT_LISTENER))
        return;
    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed() || !isInWebProcess());
    dispatchScopedEvent(FocusEvent::create(eventNames().focusoutEvent, Event::CanBubble::Yes, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(newFocusedElement)));
}

void Element::dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, const FocusOptions& options)
{
    if (auto* page = document().page())
        page->chrome().client().elementDidFocus(*this, options);
    dispatchEvent(FocusEvent::create(eventNames().focusEvent, Event::CanBubble::No, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(oldFocusedElement)));
}

void Element::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
{
    if (auto* page = document().page())
        page->chrome().client().elementDidBlur(*this);
    dispatchEvent(FocusEvent::create(eventNames().blurEvent, Event::CanBubble::No, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(newFocusedElement)));
}

void Element::dispatchWebKitImageReadyEventForTesting()
{
    if (document().settings().webkitImageReadyEventEnabled())
        dispatchEvent(Event::create("webkitImageFrameReady"_s, Event::CanBubble::Yes, Event::IsCancelable::Yes));
}

bool Element::dispatchMouseForceWillBegin()
{
#if ENABLE(MOUSE_FORCE_EVENTS)
    if (!document().hasListenerType(Document::FORCEWILLBEGIN_LISTENER))
        return false;

    Frame* frame = document().frame();
    if (!frame)
        return false;

    PlatformMouseEvent platformMouseEvent { frame->eventHandler().lastKnownMousePosition(), frame->eventHandler().lastKnownMouseGlobalPosition(), NoButton, PlatformEvent::NoType, 1, false, false, false, false, WallTime::now(), ForceAtClick, NoTap };
    auto mouseForceWillBeginEvent = MouseEvent::create(eventNames().webkitmouseforcewillbeginEvent, document().windowProxy(), platformMouseEvent, 0, nullptr);
    mouseForceWillBeginEvent->setTarget(this);
    dispatchEvent(mouseForceWillBeginEvent);

    if (mouseForceWillBeginEvent->defaultHandled() || mouseForceWillBeginEvent->defaultPrevented())
        return true;
#endif

    return false;
}

void Element::enqueueSecurityPolicyViolationEvent(SecurityPolicyViolationEventInit&& eventInit)
{
    document().eventLoop().queueTask(TaskSource::DOMManipulation, [this, protectedThis = Ref { *this }, event = SecurityPolicyViolationEvent::create(eventNames().securitypolicyviolationEvent, WTFMove(eventInit), Event::IsTrusted::Yes)] {
        if (!isConnected())
            document().dispatchEvent(event);
        else
            dispatchEvent(event);
    });
}

ExceptionOr<void> Element::mergeWithNextTextNode(Text& node)
{
    auto* next = node.nextSibling();
    if (!is<Text>(next))
        return { };
    Ref<Text> textNext { downcast<Text>(*next) };
    node.appendData(textNext->data());
    return textNext->remove();
}

String Element::innerHTML() const
{
    return serializeFragment(*this, SerializedNodes::SubtreesOfChildren);
}

String Element::outerHTML() const
{
    return serializeFragment(*this, SerializedNodes::SubtreeIncludingNode);
}

ExceptionOr<void> Element::setOuterHTML(const String& html)
{
    // The specification allows setting outerHTML on an Element whose parent is a DocumentFragment and Gecko supports this.
    // However, as of June 2021, Blink matches our behavior and throws a NoModificationAllowedError for non-Element parents.
    RefPtr parent = parentElement();
    if (UNLIKELY(!parent)) {
        if (!parentNode())
            return Exception { NoModificationAllowedError, "Cannot set outerHTML on element because it doesn't have a parent"_s };
        return Exception { NoModificationAllowedError, "Cannot set outerHTML on element because its parent is not an Element"_s };
    }

    RefPtr<Node> prev = previousSibling();
    RefPtr<Node> next = nextSibling();

    auto fragment = createFragmentForInnerOuterHTML(*parent, html, AllowScriptingContent);
    if (fragment.hasException())
        return fragment.releaseException();

    auto replaceResult = parent->replaceChild(fragment.releaseReturnValue().get(), *this);
    if (replaceResult.hasException())
        return replaceResult.releaseException();

    // The following is not part of the specification but matches Blink's behavior as of June 2021.
    RefPtr<Node> node = next ? next->previousSibling() : nullptr;
    if (is<Text>(node)) {
        auto result = mergeWithNextTextNode(downcast<Text>(*node));
        if (result.hasException())
            return result.releaseException();
    }
    if (is<Text>(prev)) {
        auto result = mergeWithNextTextNode(downcast<Text>(*prev));
        if (result.hasException())
            return result.releaseException();
    }
    return { };
}

ExceptionOr<void> Element::setInnerHTML(const String& html)
{
    ContainerNode* container;
    if (!is<HTMLTemplateElement>(*this))
        container = this;
    else
        container = &downcast<HTMLTemplateElement>(*this).content();

    // Parsing empty string creates additional elements only inside <html> container
    // https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhtml
    if (html.isEmpty() && !is<HTMLHtmlElement>(*container)) {
        ChildListMutationScope mutation(*container);
        container->removeChildren();
        return { };
    }

    auto fragment = createFragmentForInnerOuterHTML(*this, html, AllowScriptingContent);
    if (fragment.hasException())
        return fragment.releaseException();

    return replaceChildrenWithFragment(*container, fragment.releaseReturnValue());
}

String Element::innerText()
{
    // We need to update layout, since plainText uses line boxes in the render tree.
    document().updateLayoutIgnorePendingStylesheets();

    if (!renderer())
        return textContent(true);

    return plainText(makeRangeSelectingNodeContents(*this));
}

String Element::outerText()
{
    // Getting outerText is the same as getting innerText, only
    // setting is different. You would think this should get the plain
    // text for the outer range, but this is wrong, <br> for instance
    // would return different values for inner and outer text by such
    // a rule, but it doesn't in WinIE, and we want to match that.
    return innerText();
}

String Element::title() const
{
    return String();
}

const AtomString& Element::pseudo() const
{
    return attributeWithoutSynchronization(pseudoAttr);
}

void Element::setPseudo(const AtomString& value)
{
    setAttributeWithoutSynchronization(pseudoAttr, value);
}

void Element::willBecomeFullscreenElement()
{
    for (auto& child : descendantsOfType<Element>(*this))
        child.ancestorWillEnterFullscreen();
}

static void forEachRenderLayer(Element& element, const std::function<void(RenderLayer&)>& function)
{
    auto* renderer = element.renderer();
    if (!renderer || !is<RenderLayerModelObject>(renderer))
        return;
        
    auto& layerModelObject = downcast<RenderLayerModelObject>(*renderer);

    if (!is<RenderBoxModelObject>(layerModelObject)) {
        if (layerModelObject.hasLayer())
            function(*layerModelObject.layer());
        return;
    }

    RenderBoxModelObject::forRendererAndContinuations(downcast<RenderBoxModelObject>(*renderer), [function](RenderBoxModelObject& renderer) {
        if (renderer.hasLayer())
            function(*renderer.layer());
    });
}

void Element::addToTopLayer()
{
    RELEASE_ASSERT(!isInTopLayer());
    ScriptDisallowedScope scriptDisallowedScope;

    forEachRenderLayer(*this, [](RenderLayer& layer) {
        layer.establishesTopLayerWillChange();
    });

    document().addTopLayerElement(*this);
    setNodeFlag(NodeFlag::IsInTopLayer);

    // Invalidate inert state
    invalidateStyleInternal();
    if (document().documentElement())
        document().documentElement()->invalidateStyleInternal();

    forEachRenderLayer(*this, [](RenderLayer& layer) {
        layer.establishesTopLayerDidChange();
    });
}

void Element::removeFromTopLayer()
{
    RELEASE_ASSERT(isInTopLayer());
    ScriptDisallowedScope scriptDisallowedScope;

    forEachRenderLayer(*this, [](RenderLayer& layer) {
        layer.establishesTopLayerWillChange();
    });

    // We need to call Styleable::fromRenderer() while this element is still contained in
    // Document::topLayerElements(), since Styleable::fromRenderer() relies on this to
    // find the backdrop's associated element.
    if (auto* renderer = this->renderer()) {
        if (auto backdrop = renderer->backdropRenderer()) {
            if (auto styleable = Styleable::fromRenderer(*backdrop))
                styleable->cancelDeclarativeAnimations();
        }
    }

    document().removeTopLayerElement(*this);
    clearNodeFlag(NodeFlag::IsInTopLayer);

    // Invalidate inert state
    invalidateStyleInternal();
    if (document().documentElement())
        document().documentElement()->invalidateStyleInternal();
    if (auto* modalElement = document().activeModalDialog())
        modalElement->invalidateStyleInternal();

    forEachRenderLayer(*this, [](RenderLayer& layer) {
        layer.establishesTopLayerDidChange();
    });
}

static PseudoElement* beforeOrAfterPseudoElement(const Element& host, PseudoId pseudoElementSpecifier)
{
    switch (pseudoElementSpecifier) {
    case PseudoId::Before:
        return host.beforePseudoElement();
    case PseudoId::After:
        return host.afterPseudoElement();
    default:
        return nullptr;
    }
}

const RenderStyle* Element::existingComputedStyle() const
{
    if (hasRareData()) {
        if (auto* style = elementRareData()->computedStyle())
            return style;
    }

    return renderStyle();
}

const RenderStyle* Element::renderOrDisplayContentsStyle(PseudoId pseudoId) const
{
    if (pseudoId != PseudoId::None) {
        if (auto* pseudoElement = beforeOrAfterPseudoElement(*this, pseudoId))
            return pseudoElement->renderOrDisplayContentsStyle();

        if (auto* computedStyle = existingComputedStyle()) {
            if (auto* cachedPseudoStyle = computedStyle->getCachedPseudoStyle(pseudoId))
                return cachedPseudoStyle;
        }

        return nullptr;
    }

    if (auto* style = renderStyle())
        return style;

    if (!hasRareData())
        return nullptr;
    auto* style = elementRareData()->computedStyle();
    if (style && style->display() == DisplayType::Contents)
        return style;

    return nullptr;
}

const RenderStyle* Element::resolveComputedStyle(ResolveComputedStyleMode mode)
{
    ASSERT(isConnected());
    ASSERT(!existingComputedStyle() || hasNodeFlag(NodeFlag::IsComputedStyleInvalidFlag));

    Deque<RefPtr<Element>, 32> elementsRequiringComputedStyle({ this });
    const RenderStyle* computedStyle = nullptr;

    // Collect ancestors until we find one that has style.
    for (auto& ancestor : composedTreeAncestors(*this)) {
        if (auto* existingStyle = ancestor.existingComputedStyle()) {
            computedStyle = existingStyle;
            break;
        }
        elementsRequiringComputedStyle.prepend(&ancestor);
    }

    // On iOS request delegates called during styleForElement may result in re-entering WebKit and killing the style resolver.
    Style::PostResolutionCallbackDisabler disabler(document(), Style::PostResolutionCallbackDisabler::DrainCallbacks::No);

    // Resolve and cache styles starting from the most distant ancestor.
    for (auto& element : elementsRequiringComputedStyle) {
        auto style = document().styleForElementIgnoringPendingStylesheets(*element, computedStyle);
        computedStyle = style.get();
        ElementRareData& rareData = element->ensureElementRareData();
        rareData.setComputedStyle(WTFMove(style));
        element->clearNodeFlag(NodeFlag::IsComputedStyleInvalidFlag);

        if (mode == ResolveComputedStyleMode::RenderedOnly && computedStyle->display() == DisplayType::None)
            return nullptr;
    }

    return computedStyle;
}

bool Element::hasValidStyle() const
{
    if (!document().needsStyleRecalc())
        return true;

    if (document().hasPendingFullStyleRebuild())
        return false;
    
    for (auto& element : lineageOfType<Element>(*this)) {
        if (element.styleValidity() != Style::Validity::Valid)
            return false;
    }
    return true;
}

bool Element::isFocusableWithoutResolvingFullStyle() const
{
    auto isFocusableStyle = [](const RenderStyle* style) {
        return style
            && style->display() != DisplayType::None
            && style->display() != DisplayType::Contents
            && style->visibility() == Visibility::Visible
            && !style->effectiveInert();
    };

    if (renderStyle() || hasValidStyle())
        return isFocusableStyle(renderStyle());

    auto computedStyleForElement = [](Element& element) -> const RenderStyle* {
        auto* style = element.hasNodeFlag(NodeFlag::IsComputedStyleInvalidFlag) ? nullptr : element.existingComputedStyle();
        return style ? style : element.resolveComputedStyle(ResolveComputedStyleMode::RenderedOnly);
    };

    // Compute style in yet unstyled subtree.
    auto* style = computedStyleForElement(const_cast<Element&>(*this));
    if (!isFocusableStyle(style))
        return false;

    for (auto& element : composedTreeAncestors(const_cast<Element&>(*this))) {
        auto* style = computedStyleForElement(element);
        if (!style || style->display() == DisplayType::None)
            return false;
    }

    return true;
}

const RenderStyle& Element::resolvePseudoElementStyle(PseudoId pseudoElementSpecifier)
{
    ASSERT(!isPseudoElement());

    auto* parentStyle = existingComputedStyle();
    ASSERT(parentStyle);
    ASSERT(!parentStyle->getCachedPseudoStyle(pseudoElementSpecifier));

    Style::PostResolutionCallbackDisabler disabler(document(), Style::PostResolutionCallbackDisabler::DrainCallbacks::No);

    auto style = document().styleForElementIgnoringPendingStylesheets(*this, parentStyle, pseudoElementSpecifier);
    if (!style) {
        style = RenderStyle::createPtr();
        style->inheritFrom(*parentStyle);
        style->setStyleType(pseudoElementSpecifier);
    }

    auto* computedStyle = style.get();
    const_cast<RenderStyle*>(parentStyle)->addCachedPseudoStyle(WTFMove(style));
    return *computedStyle;
}

const RenderStyle* Element::computedStyle(PseudoId pseudoElementSpecifier)
{
    if (!isConnected())
        return nullptr;

    if (PseudoElement* pseudoElement = beforeOrAfterPseudoElement(*this, pseudoElementSpecifier))
        return pseudoElement->computedStyle();

    auto* style = existingComputedStyle();
    if (!style)
        style = resolveComputedStyle();

    if (pseudoElementSpecifier != PseudoId::None) {
        if (auto* cachedPseudoStyle = style->getCachedPseudoStyle(pseudoElementSpecifier))
            return cachedPseudoStyle;
        return &resolvePseudoElementStyle(pseudoElementSpecifier);
    }

    return style;
}

bool Element::needsStyleInvalidation() const
{
    if (!inRenderedDocument())
        return false;
    // If :has() is present a change in an element may affect elements outside its subtree.
    if (styleValidity() >= Style::Validity::SubtreeInvalid && !Style::Scope::forNode(*this).usesHasPseudoClass())
        return false;
    if (document().documentElement() && document().documentElement()->styleValidity() >= Style::Validity::SubtreeInvalid)
        return false;
    if (document().hasPendingFullStyleRebuild())
        return false;

    return true;
}

void Element::setChildIndex(unsigned index)
{
    ElementRareData& rareData = ensureElementRareData();
    rareData.setChildIndex(index);
}

bool Element::hasFlagsSetDuringStylingOfChildren() const
{
    return childrenAffectedByFirstChildRules()
        || childrenAffectedByLastChildRules()
        || childrenAffectedByForwardPositionalRules()
        || descendantsAffectedByForwardPositionalRules()
        || childrenAffectedByBackwardPositionalRules()
        || descendantsAffectedByBackwardPositionalRules()
        || childrenAffectedByPropertyBasedBackwardPositionalRules();
}

unsigned Element::rareDataChildIndex() const
{
    ASSERT(hasRareData());
    return elementRareData()->childIndex();
}

AtomString Element::computeInheritedLanguage() const
{
    // The language property is inherited, so we iterate over the parents to find the first language.
    for (auto& element : lineageOfType<Element>(*this)) {
        if (auto* elementData = element.elementData()) {
            if (auto* attribute = elementData->findLanguageAttribute())
                return attribute->value();
        }
    }
    return document().contentLanguage();
}

Locale& Element::locale() const
{
    return document().getCachedLocale(computeInheritedLanguage());
}

void Element::normalizeAttributes()
{
    if (!hasAttributes())
        return;

    auto* attrNodeList = attrNodeListForElement(*this);
    if (!attrNodeList)
        return;

    // Copy the Attr Vector because Node::normalize() can fire synchronous JS
    // events (e.g. DOMSubtreeModified) and a JS listener could add / remove
    // attributes while we are iterating.
    auto copyOfAttrNodeList = *attrNodeList;
    for (auto& attrNode : copyOfAttrNodeList)
        attrNode->normalize();
}

PseudoElement& Element::ensurePseudoElement(PseudoId pseudoId)
{
    if (pseudoId == PseudoId::Before) {
        if (!beforePseudoElement())
            ensureElementRareData().setBeforePseudoElement(PseudoElement::create(*this, pseudoId));
        return *beforePseudoElement();
    }

    ASSERT(pseudoId == PseudoId::After);
    if (!afterPseudoElement())
        ensureElementRareData().setAfterPseudoElement(PseudoElement::create(*this, pseudoId));
    return *afterPseudoElement();
}

PseudoElement* Element::beforePseudoElement() const
{
    return hasRareData() ? elementRareData()->beforePseudoElement() : nullptr;
}

PseudoElement* Element::afterPseudoElement() const
{
    return hasRareData() ? elementRareData()->afterPseudoElement() : nullptr;
}

static void disconnectPseudoElement(PseudoElement* pseudoElement)
{
    if (!pseudoElement)
        return;
    ASSERT(!pseudoElement->renderer());
    ASSERT(pseudoElement->hostElement());
    pseudoElement->clearHostElement();
}

void Element::clearBeforePseudoElementSlow()
{
    ASSERT(hasRareData());
    disconnectPseudoElement(elementRareData()->beforePseudoElement());
    elementRareData()->setBeforePseudoElement(nullptr);
}

void Element::clearAfterPseudoElementSlow()
{
    ASSERT(hasRareData());
    disconnectPseudoElement(elementRareData()->afterPseudoElement());
    elementRareData()->setAfterPseudoElement(nullptr);
}

bool Element::matchesValidPseudoClass() const
{
    return false;
}

bool Element::matchesInvalidPseudoClass() const
{
    return false;
}

bool Element::matchesReadWritePseudoClass() const
{
    return false;
}

bool Element::matchesIndeterminatePseudoClass() const
{
    return shouldAppearIndeterminate();
}

bool Element::matchesDefaultPseudoClass() const
{
    return false;
}

ExceptionOr<bool> Element::matches(const String& selector)
{
    auto query = document().selectorQueryForString(selector);
    if (query.hasException())
        return query.releaseException();
    return query.releaseReturnValue().matches(*this);
}

ExceptionOr<Element*> Element::closest(const String& selector)
{
    auto query = document().selectorQueryForString(selector);
    if (query.hasException())
        return query.releaseException();
    return query.releaseReturnValue().closest(*this);
}

bool Element::shouldAppearIndeterminate() const
{
    return false;
}

bool Element::mayCauseRepaintInsideViewport(const IntRect* visibleRect) const
{
    return renderer() && renderer()->mayCauseRepaintInsideViewport(visibleRect);
}

DOMTokenList& Element::classList()
{
    ElementRareData& data = ensureElementRareData();
    if (!data.classList())
        data.setClassList(makeUnique<DOMTokenList>(*this, HTMLNames::classAttr));
    return *data.classList();
}

SpaceSplitString Element::partNames() const
{
    return hasRareData() ? elementRareData()->partNames() : SpaceSplitString();
}

DOMTokenList& Element::part()
{
    auto& data = ensureElementRareData();
    if (!data.partList())
        data.setPartList(makeUnique<DOMTokenList>(*this, HTMLNames::partAttr));
    return *data.partList();
}

DatasetDOMStringMap& Element::dataset()
{
    ElementRareData& data = ensureElementRareData();
    if (!data.dataset())
        data.setDataset(makeUnique<DatasetDOMStringMap>(*this));
    return *data.dataset();
}

URL Element::getURLAttribute(const QualifiedName& name) const
{
#if ASSERT_ENABLED
    if (elementData()) {
        if (const Attribute* attribute = findAttributeByName(name))
            ASSERT(isURLAttribute(*attribute));
    }
#endif
    return document().completeURL(getAttribute(name));
}

URL Element::getNonEmptyURLAttribute(const QualifiedName& name) const
{
#if ASSERT_ENABLED
    if (elementData()) {
        if (const Attribute* attribute = findAttributeByName(name))
            ASSERT(isURLAttribute(*attribute));
    }
#endif
    String value = stripLeadingAndTrailingHTMLSpaces(getAttribute(name));
    if (value.isEmpty())
        return URL();
    return document().completeURL(value);
}

int Element::getIntegralAttribute(const QualifiedName& attributeName) const
{
    return parseHTMLInteger(getAttribute(attributeName)).value_or(0);
}

void Element::setIntegralAttribute(const QualifiedName& attributeName, int value)
{
    setAttribute(attributeName, AtomString::number(value));
}

unsigned Element::getUnsignedIntegralAttribute(const QualifiedName& attributeName) const
{
    return parseHTMLNonNegativeInteger(getAttribute(attributeName)).value_or(0);
}

void Element::setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value)
{
    setAttribute(attributeName, AtomString::number(limitToOnlyHTMLNonNegative(value)));
}

bool Element::childShouldCreateRenderer(const Node& child) const
{
    // Only create renderers for SVG elements whose parents are SVG elements, or for proper <svg xmlns="svgNS"> subdocuments.
    if (child.isSVGElement()) {
        ASSERT(!isSVGElement());
        const SVGElement& childElement = downcast<SVGElement>(child);
        return is<SVGSVGElement>(childElement) && childElement.isValid();
    }
    return true;
}

#if ENABLE(FULLSCREEN_API)

static Element* parentCrossingFrameBoundaries(const Element* element)
{
    ASSERT(element);
    if (auto* parent = element->parentElementInComposedTree())
        return parent;
    return element->document().ownerElement();
}

void Element::webkitRequestFullscreen()
{
    document().fullscreenManager().requestFullscreenForElement(*this, FullscreenManager::EnforceIFrameAllowFullscreenRequirement);
}

void Element::setContainsFullScreenElement(bool flag)
{
    if (flag)
        setNodeFlag(NodeFlag::ContainsFullScreenElement);
    else
        clearNodeFlag(NodeFlag::ContainsFullScreenElement);
    invalidateStyleAndLayerComposition();
}

void Element::setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool flag)
{
    Element* element = this;
    while ((element = parentCrossingFrameBoundaries(element)))
        element->setContainsFullScreenElement(flag);
}

#endif

ExceptionOr<void> Element::setPointerCapture(int32_t pointerId)
{
    if (document().page())
        return document().page()->pointerCaptureController().setPointerCapture(this, pointerId);
    return { };
}

ExceptionOr<void> Element::releasePointerCapture(int32_t pointerId)
{
    if (document().page())
        return document().page()->pointerCaptureController().releasePointerCapture(this, pointerId);
    return { };
}

bool Element::hasPointerCapture(int32_t pointerId)
{
    if (document().page())
        return document().page()->pointerCaptureController().hasPointerCapture(this, pointerId);
    return false;
}

#if ENABLE(POINTER_LOCK)

void Element::requestPointerLock()
{
    if (document().page())
        document().page()->pointerLockController().requestPointerLock(this);
}

#endif

void Element::disconnectFromIntersectionObservers()
{
    auto* observerData = intersectionObserverDataIfExists();
    if (!observerData)
        return;

    for (const auto& registration : observerData->registrations) {
        if (registration.observer)
            registration.observer->targetDestroyed(*this);
    }
    observerData->registrations.clear();

    for (const auto& observer : observerData->observers) {
        if (observer)
            observer->rootDestroyed();
    }
    observerData->observers.clear();
}

IntersectionObserverData& Element::ensureIntersectionObserverData()
{
    auto& rareData = ensureElementRareData();
    if (!rareData.intersectionObserverData())
        rareData.setIntersectionObserverData(makeUnique<IntersectionObserverData>());
    return *rareData.intersectionObserverData();
}

IntersectionObserverData* Element::intersectionObserverDataIfExists()
{
    return hasRareData() ? elementRareData()->intersectionObserverData() : nullptr;
}

ElementAnimationRareData* Element::animationRareData(PseudoId pseudoId) const
{
    return hasRareData() ? elementRareData()->animationRareData(pseudoId) : nullptr;
}

ElementAnimationRareData& Element::ensureAnimationRareData(PseudoId pseudoId)
{
    return ensureElementRareData().ensureAnimationRareData(pseudoId);
}

KeyframeEffectStack* Element::keyframeEffectStack(PseudoId pseudoId) const
{
    if (auto* animationData = animationRareData(pseudoId))
        return animationData->keyframeEffectStack();
    return nullptr;
}

KeyframeEffectStack& Element::ensureKeyframeEffectStack(PseudoId pseudoId)
{
    return ensureAnimationRareData(pseudoId).ensureKeyframeEffectStack();
}

bool Element::hasKeyframeEffects(PseudoId pseudoId) const
{
    if (auto* animationData = animationRareData(pseudoId)) {
        if (auto* keyframeEffectStack = animationData->keyframeEffectStack())
            return keyframeEffectStack->hasEffects();
    }
    return false;
}

const AnimationCollection* Element::animations(PseudoId pseudoId) const
{
    if (auto* animationData = animationRareData(pseudoId))
        return &animationData->animations();
    return nullptr;
}

bool Element::hasCompletedTransitionForProperty(PseudoId pseudoId, CSSPropertyID property) const
{
    if (auto* animationData = animationRareData(pseudoId))
        return animationData->completedTransitionsByProperty().contains(property);
    return false;
}

bool Element::hasRunningTransitionForProperty(PseudoId pseudoId, CSSPropertyID property) const
{
    if (auto* animationData = animationRareData(pseudoId))
        return animationData->runningTransitionsByProperty().contains(property);
    return false;
}

bool Element::hasRunningTransitions(PseudoId pseudoId) const
{
    if (auto* animationData = animationRareData(pseudoId))
        return !animationData->runningTransitionsByProperty().isEmpty();
    return false;
}

AnimationCollection& Element::ensureAnimations(PseudoId pseudoId)
{
    return ensureAnimationRareData(pseudoId).animations();
}

CSSAnimationCollection& Element::animationsCreatedByMarkup(PseudoId pseudoId)
{
    return ensureAnimationRareData(pseudoId).animationsCreatedByMarkup();
}

void Element::setAnimationsCreatedByMarkup(PseudoId pseudoId, CSSAnimationCollection&& animations)
{
    if (animations.isEmpty() && !animationRareData(pseudoId))
        return;
    ensureAnimationRareData(pseudoId).setAnimationsCreatedByMarkup(WTFMove(animations));
}

PropertyToTransitionMap& Element::ensureCompletedTransitionsByProperty(PseudoId pseudoId)
{
    return ensureAnimationRareData(pseudoId).completedTransitionsByProperty();
}

PropertyToTransitionMap& Element::ensureRunningTransitionsByProperty(PseudoId pseudoId)
{
    return ensureAnimationRareData(pseudoId).runningTransitionsByProperty();
}

const RenderStyle* Element::lastStyleChangeEventStyle(PseudoId pseudoId) const
{
    if (auto* animationData = animationRareData(pseudoId))
        return animationData->lastStyleChangeEventStyle();
    return nullptr;
}

void Element::setLastStyleChangeEventStyle(PseudoId pseudoId, std::unique_ptr<const RenderStyle>&& style)
{
    if (auto* animationData = animationRareData(pseudoId))
        animationData->setLastStyleChangeEventStyle(WTFMove(style));
    else if (style)
        ensureAnimationRareData(pseudoId).setLastStyleChangeEventStyle(WTFMove(style));
}

void Element::cssAnimationsDidUpdate(PseudoId pseudoId)
{
    ensureAnimationRareData(pseudoId).cssAnimationsDidUpdate();
}

void Element::keyframesRuleDidChange(PseudoId pseudoId)
{
    ensureAnimationRareData(pseudoId).keyframesRuleDidChange();
}

bool Element::hasPendingKeyframesUpdate(PseudoId pseudoId) const
{
    auto* data = animationRareData(pseudoId);
    return data && data->hasPendingKeyframesUpdate();
}

void Element::disconnectFromResizeObservers()
{
    auto* observerData = resizeObserverData();
    if (!observerData)
        return;

    for (const auto& observer : observerData->observers)
        observer->targetDestroyed(*this);
    observerData->observers.clear();
}

ResizeObserverData& Element::ensureResizeObserverData()
{
    auto& rareData = ensureElementRareData();
    if (!rareData.resizeObserverData())
        rareData.setResizeObserverData(makeUnique<ResizeObserverData>());
    return *rareData.resizeObserverData();
}

ResizeObserverData* Element::resizeObserverData()
{
    return hasRareData() ? elementRareData()->resizeObserverData() : nullptr;
}

bool Element::isSpellCheckingEnabled() const
{
    for (auto* ancestor = this; ancestor; ancestor = ancestor->parentOrShadowHostElement()) {
        auto& value = ancestor->attributeWithoutSynchronization(HTMLNames::spellcheckAttr);
        if (value.isNull())
            continue;
        if (value.isEmpty() || equalLettersIgnoringASCIICase(value, "true"_s))
            return true;
        if (equalLettersIgnoringASCIICase(value, "false"_s))
            return false;
    }
    return true;
}

#if ASSERT_ENABLED
bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
{
    if (name == HTMLNames::styleAttr)
        return false;

    if (isSVGElement())
        return !downcast<SVGElement>(*this).isAnimatedPropertyAttribute(name);

    return true;
}
#endif

#if DUMP_NODE_STATISTICS
bool Element::hasNamedNodeMap() const
{
    return hasRareData() && elementRareData()->attributeMap();
}
#endif

inline void Element::updateName(const AtomString& oldName, const AtomString& newName)
{
    if (!isInTreeScope())
        return;

    if (oldName == newName)
        return;

    updateNameForTreeScope(treeScope(), oldName, newName);

    if (!isConnected())
        return;
    if (!is<HTMLDocument>(document()))
        return;
    updateNameForDocument(downcast<HTMLDocument>(document()), oldName, newName);
}

void Element::updateNameForTreeScope(TreeScope& scope, const AtomString& oldName, const AtomString& newName)
{
    ASSERT(oldName != newName);

    if (!oldName.isEmpty())
        scope.removeElementByName(*oldName.impl(), *this);
    if (!newName.isEmpty())
        scope.addElementByName(*newName.impl(), *this);
}

void Element::updateNameForDocument(HTMLDocument& document, const AtomString& oldName, const AtomString& newName)
{
    ASSERT(oldName != newName);

    if (isInShadowTree())
        return;

    if (WindowNameCollection::elementMatchesIfNameAttributeMatch(*this)) {
        const AtomString& id = WindowNameCollection::elementMatchesIfIdAttributeMatch(*this) ? getIdAttribute() : nullAtom();
        if (!oldName.isEmpty() && oldName != id)
            document.removeWindowNamedItem(*oldName.impl(), *this);
        if (!newName.isEmpty() && newName != id)
            document.addWindowNamedItem(*newName.impl(), *this);
    }

    if (DocumentNameCollection::elementMatchesIfNameAttributeMatch(*this)) {
        const AtomString& id = DocumentNameCollection::elementMatchesIfIdAttributeMatch(*this) ? getIdAttribute() : nullAtom();
        if (!oldName.isEmpty() && oldName != id)
            document.removeDocumentNamedItem(*oldName.impl(), *this);
        if (!newName.isEmpty() && newName != id)
            document.addDocumentNamedItem(*newName.impl(), *this);
    }
}

inline void Element::updateId(const AtomString& oldId, const AtomString& newId, NotifyObservers notifyObservers)
{
    if (!isInTreeScope())
        return;

    if (oldId == newId)
        return;

    updateIdForTreeScope(treeScope(), oldId, newId, notifyObservers);

    if (!isConnected())
        return;
    if (!is<HTMLDocument>(document()))
        return;
    updateIdForDocument(downcast<HTMLDocument>(document()), oldId, newId, UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute);
}

void Element::updateIdForTreeScope(TreeScope& scope, const AtomString& oldId, const AtomString& newId, NotifyObservers notifyObservers)
{
    ASSERT(isInTreeScope());
    ASSERT(oldId != newId);

    if (!oldId.isEmpty())
        scope.removeElementById(*oldId.impl(), *this, notifyObservers == NotifyObservers::Yes);
    if (!newId.isEmpty())
        scope.addElementById(*newId.impl(), *this, notifyObservers == NotifyObservers::Yes);
}

void Element::updateIdForDocument(HTMLDocument& document, const AtomString& oldId, const AtomString& newId, HTMLDocumentNamedItemMapsUpdatingCondition condition)
{
    ASSERT(isConnected());
    ASSERT(oldId != newId);

    if (isInShadowTree())
        return;

    if (WindowNameCollection::elementMatchesIfIdAttributeMatch(*this)) {
        const AtomString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && WindowNameCollection::elementMatchesIfNameAttributeMatch(*this) ? getNameAttribute() : nullAtom();
        if (!oldId.isEmpty() && oldId != name)
            document.removeWindowNamedItem(*oldId.impl(), *this);
        if (!newId.isEmpty() && newId != name)
            document.addWindowNamedItem(*newId.impl(), *this);
    }

    if (DocumentNameCollection::elementMatchesIfIdAttributeMatch(*this)) {
        const AtomString& name = condition == UpdateHTMLDocumentNamedItemMapsOnlyIfDiffersFromNameAttribute && DocumentNameCollection::elementMatchesIfNameAttributeMatch(*this) ? getNameAttribute() : nullAtom();
        if (!oldId.isEmpty() && oldId != name)
            document.removeDocumentNamedItem(*oldId.impl(), *this);
        if (!newId.isEmpty() && newId != name)
            document.addDocumentNamedItem(*newId.impl(), *this);
    }
}

void Element::updateLabel(TreeScope& scope, const AtomString& oldForAttributeValue, const AtomString& newForAttributeValue)
{
    ASSERT(hasTagName(labelTag));

    if (!isConnected())
        return;

    if (oldForAttributeValue == newForAttributeValue)
        return;

    if (!oldForAttributeValue.isEmpty())
        scope.removeLabel(*oldForAttributeValue.impl(), downcast<HTMLLabelElement>(*this));
    if (!newForAttributeValue.isEmpty())
        scope.addLabel(*newForAttributeValue.impl(), downcast<HTMLLabelElement>(*this));
}

void Element::willModifyAttribute(const QualifiedName& name, const AtomString& oldValue, const AtomString& newValue)
{
    if (name == HTMLNames::idAttr)
        updateId(oldValue, newValue, NotifyObservers::No); // Will notify observers after the attribute is actually changed.
    else if (name == HTMLNames::nameAttr)
        updateName(oldValue, newValue);
    else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
        if (treeScope().shouldCacheLabelsByForAttribute())
            updateLabel(treeScope(), oldValue, newValue);
    }

    if (auto recipients = MutationObserverInterestGroup::createForAttributesMutation(*this, name))
        recipients->enqueueMutationRecord(MutationRecord::createAttributes(*this, name, oldValue));

    InspectorInstrumentation::willModifyDOMAttr(document(), *this, oldValue, newValue);
}

void Element::didAddAttribute(const QualifiedName& name, const AtomString& value)
{
    attributeChanged(name, nullAtom(), value);
    InspectorInstrumentation::didModifyDOMAttr(document(), *this, name.toAtomString(), value);
    dispatchSubtreeModifiedEvent();
}

void Element::didModifyAttribute(const QualifiedName& name, const AtomString& oldValue, const AtomString& newValue)
{
    attributeChanged(name, oldValue, newValue);
    InspectorInstrumentation::didModifyDOMAttr(document(), *this, name.toAtomString(), newValue);
    // Do not dispatch a DOMSubtreeModified event here; see bug 81141.
}

void Element::didRemoveAttribute(const QualifiedName& name, const AtomString& oldValue)
{
    attributeChanged(name, oldValue, nullAtom());
    InspectorInstrumentation::didRemoveDOMAttr(document(), *this, name.toAtomString());
    dispatchSubtreeModifiedEvent();
}

IntPoint Element::savedLayerScrollPosition() const
{
    return hasRareData() ? elementRareData()->savedLayerScrollPosition() : IntPoint();
}

void Element::setSavedLayerScrollPositionSlow(const IntPoint& position)
{
    ASSERT(!position.isZero() || hasRareData());
    ensureElementRareData().setSavedLayerScrollPosition(position);
}

RefPtr<Attr> Element::attrIfExists(const AtomString& localName, bool shouldIgnoreAttributeCase)
{
    if (auto* attrNodeList = attrNodeListForElement(*this))
        return findAttrNodeInList(*attrNodeList, localName, shouldIgnoreAttributeCase);
    return nullptr;
}

RefPtr<Attr> Element::attrIfExists(const QualifiedName& name)
{
    if (auto* attrNodeList = attrNodeListForElement(*this))
        return findAttrNodeInList(*attrNodeList, name);
    return nullptr;
}

Ref<Attr> Element::ensureAttr(const QualifiedName& name)
{
    auto& attrNodeList = ensureAttrNodeListForElement(*this);
    RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, name);
    if (!attrNode) {
        attrNode = Attr::create(*this, name);
        attrNode->setTreeScopeRecursively(treeScope());
        attrNodeList.append(attrNode);
    }
    return attrNode.releaseNonNull();
}

void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomString& value)
{
    ASSERT(hasSyntheticAttrChildNodes());
    attrNode->detachFromElementWithValue(value);

    auto& attrNodeList = *attrNodeListForElement(*this);
    bool found = attrNodeList.removeFirstMatching([attrNode](auto& attribute) {
        return attribute->qualifiedName() == attrNode->qualifiedName();
    });
    ASSERT_UNUSED(found, found);
    if (attrNodeList.isEmpty())
        removeAttrNodeListForElement(*this);
}

void Element::detachAllAttrNodesFromElement()
{
    auto* attrNodeList = attrNodeListForElement(*this);
    ASSERT(attrNodeList);

    for (const Attribute& attribute : attributesIterator()) {
        if (RefPtr<Attr> attrNode = findAttrNodeInList(*attrNodeList, attribute.name()))
            attrNode->detachFromElementWithValue(attribute.value());
    }

    removeAttrNodeListForElement(*this);
}

void Element::resetComputedStyle()
{
    if (!hasRareData() || !elementRareData()->computedStyle())
        return;

    auto reset = [](Element& element) {
        if (element.hasCustomStyleResolveCallbacks())
            element.willResetComputedStyle();
        element.elementRareData()->resetComputedStyle();
    };
    reset(*this);
    for (auto& child : descendantsOfType<Element>(*this)) {
        if (!child.hasRareData() || !child.elementRareData()->computedStyle() || child.hasDisplayContents())
            continue;
        reset(child);
    }
}

void Element::resetStyleRelations()
{
    clearStyleFlags(NodeStyleFlag::StyleAffectedByEmpty);
    if (!hasRareData())
        return;
    elementRareData()->setChildIndex(0);
}

void Element::resetChildStyleRelations()
{
    clearStyleFlags({
        NodeStyleFlag::ChildrenAffectedByFirstChildRules,
        NodeStyleFlag::ChildrenAffectedByLastChildRules,
        NodeStyleFlag::ChildrenAffectedByForwardPositionalRules,
        NodeStyleFlag::ChildrenAffectedByBackwardPositionalRules,
        NodeStyleFlag::ChildrenAffectedByPropertyBasedBackwardPositionalRules
    });
}

void Element::resetAllDescendantStyleRelations()
{
    resetChildStyleRelations();
    
    clearStyleFlags({
        NodeStyleFlag::DescendantsAffectedByForwardPositionalRules,
        NodeStyleFlag::DescendantsAffectedByBackwardPositionalRules
    });
}

void Element::clearHoverAndActiveStatusBeforeDetachingRenderer()
{
    if (!isUserActionElement())
        return;
    if (hovered())
        document().hoveredElementDidDetach(*this);
    if (isInActiveChain())
        document().elementInActiveChainDidDetach(*this);
    document().userActionElements().clearActiveAndHovered(*this);
}

void Element::willRecalcStyle(Style::Change)
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

void Element::didRecalcStyle(Style::Change)
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

void Element::willResetComputedStyle()
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

void Element::willAttachRenderers()
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

void Element::didAttachRenderers()
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

void Element::willDetachRenderers()
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

void Element::didDetachRenderers()
{
    ASSERT(hasCustomStyleResolveCallbacks());
}

std::optional<Style::ElementStyle> Element::resolveCustomStyle(const Style::ResolutionContext&, const RenderStyle*)
{
    ASSERT(hasCustomStyleResolveCallbacks());
    return std::nullopt;
}

void Element::cloneAttributesFromElement(const Element& other)
{
    if (hasSyntheticAttrChildNodes())
        detachAllAttrNodesFromElement();

    other.synchronizeAllAttributes();
    if (!other.m_elementData) {
        m_elementData = nullptr;
        return;
    }

    // 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.
    // Fortunately, those named item maps are only updated when this element is in the document, which should never be the case.
    ASSERT(!isConnected());

    const AtomString& oldID = getIdAttribute();
    const AtomString& newID = other.getIdAttribute();

    if (!oldID.isNull() || !newID.isNull())
        updateId(oldID, newID, NotifyObservers::No); // Will notify observers after the attribute is actually changed.

    const AtomString& oldName = getNameAttribute();
    const AtomString& newName = other.getNameAttribute();

    if (!oldName.isNull() || !newName.isNull())
        updateName(oldName, newName);

    // If 'other' has a mutable ElementData, convert it to an immutable one so we can share it between both elements.
    // We can only do this if there is no CSSOM wrapper for other's inline style, and there are no presentation attributes.
    if (is<UniqueElementData>(*other.m_elementData)
        && !other.m_elementData->presentationalHintStyle()
        && (!other.m_elementData->inlineStyle() || !other.m_elementData->inlineStyle()->hasCSSOMWrapper()))
        const_cast<Element&>(other).m_elementData = downcast<UniqueElementData>(*other.m_elementData).makeShareableCopy();

    if (!other.m_elementData->isUnique())
        m_elementData = other.m_elementData;
    else
        m_elementData = other.m_elementData->makeUniqueCopy();

    for (const Attribute& attribute : attributesIterator())
        attributeChanged(attribute.name(), nullAtom(), attribute.value(), ModifiedByCloning);

    setNonce(other.nonce());
}

void Element::cloneDataFromElement(const Element& other)
{
    cloneAttributesFromElement(other);
    copyNonAttributePropertiesFromElement(other);
}

void Element::createUniqueElementData()
{
    if (!m_elementData)
        m_elementData = UniqueElementData::create();
    else
        m_elementData = downcast<ShareableElementData>(*m_elementData).makeUniqueCopy();
}

bool Element::canContainRangeEndPoint() const
{
    return !equalLettersIgnoringASCIICase(attributeWithoutSynchronization(roleAttr), "img"_s);
}

String Element::completeURLsInAttributeValue(const URL& base, const Attribute& attribute) const
{
    return URL(base, attribute.value()).string();
}

ExceptionOr<Node*> Element::insertAdjacent(const String& where, Ref<Node>&& newChild)
{
    // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
    // a document fragment is created and the elements appended in the correct order. This document
    // fragment isn't returned anywhere.
    //
    // This is impossible for us to implement as the DOM tree does not allow for such structures,
    // Opera also appears to disallow such usage.

    if (equalLettersIgnoringASCIICase(where, "beforebegin"_s)) {
        auto* parent = this->parentNode();
        if (!parent)
            return nullptr;
        auto result = parent->insertBefore(newChild, this);
        if (result.hasException())
            return result.releaseException();
        return newChild.ptr();
    }

    if (equalLettersIgnoringASCIICase(where, "afterbegin"_s)) {
        auto result = insertBefore(newChild, firstChild());
        if (result.hasException())
            return result.releaseException();
        return newChild.ptr();
    }

    if (equalLettersIgnoringASCIICase(where, "beforeend"_s)) {
        auto result = appendChild(newChild);
        if (result.hasException())
            return result.releaseException();
        return newChild.ptr();
    }

    if (equalLettersIgnoringASCIICase(where, "afterend"_s)) {
        auto* parent = this->parentNode();
        if (!parent)
            return nullptr;
        auto result = parent->insertBefore(newChild, nextSibling());
        if (result.hasException())
            return result.releaseException();
        return newChild.ptr();
    }

    return Exception { SyntaxError };
}

ExceptionOr<Element*> Element::insertAdjacentElement(const String& where, Element& newChild)
{
    auto result = insertAdjacent(where, newChild);
    if (result.hasException())
        return result.releaseException();
    return downcast<Element>(result.releaseReturnValue());
}

// Step 1 of https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml.
static ExceptionOr<ContainerNode&> contextNodeForInsertion(const String& where, Element& element)
{
    if (equalLettersIgnoringASCIICase(where, "beforebegin"_s) || equalLettersIgnoringASCIICase(where, "afterend"_s)) {
        auto* parent = element.parentNode();
        if (!parent || is<Document>(*parent))
            return Exception { NoModificationAllowedError };
        return *parent;
    }
    if (equalLettersIgnoringASCIICase(where, "afterbegin"_s) || equalLettersIgnoringASCIICase(where, "beforeend"_s))
        return element;
    return Exception { SyntaxError };
}

// Step 2 of https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml.
static ExceptionOr<Ref<Element>> contextElementForInsertion(const String& where, Element& element)
{
    auto contextNodeResult = contextNodeForInsertion(where, element);
    if (contextNodeResult.hasException())
        return contextNodeResult.releaseException();
    auto& contextNode = contextNodeResult.releaseReturnValue();
    if (!is<Element>(contextNode) || (contextNode.document().isHTMLDocument() && is<HTMLHtmlElement>(contextNode)))
        return Ref<Element> { HTMLBodyElement::create(contextNode.document()) };
    return Ref<Element> { downcast<Element>(contextNode) };
}

// https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml
ExceptionOr<void> Element::insertAdjacentHTML(const String& where, const String& markup, NodeVector* addedNodes)
{
    // Steps 1 and 2.
    auto contextElement = contextElementForInsertion(where, *this);
    if (contextElement.hasException())
        return contextElement.releaseException();
    // Step 3.
    auto fragment = createFragmentForInnerOuterHTML(contextElement.releaseReturnValue(), markup, AllowScriptingContent);
    if (fragment.hasException())
        return fragment.releaseException();

    if (UNLIKELY(addedNodes)) {
        // Must be called before insertAdjacent, as otherwise the children of fragment will be moved
        // to their new parent and will be harder to keep track of.
        collectChildNodes(fragment.returnValue(), *addedNodes);
    }

    // Step 4.
    auto result = insertAdjacent(where, fragment.releaseReturnValue());
    if (result.hasException())
        return result.releaseException();
    return { };
}

ExceptionOr<void> Element::insertAdjacentHTML(const String& where, const String& markup)
{
    return insertAdjacentHTML(where, markup, nullptr);
}

ExceptionOr<void> Element::insertAdjacentText(const String& where, String&& text)
{
    auto result = insertAdjacent(where, document().createTextNode(WTFMove(text)));
    if (result.hasException())
        return result.releaseException();
    return { };
}

Element* Element::findAnchorElementForLink(String& outAnchorName)
{
    if (!isLink())
        return nullptr;

    const AtomString& href = attributeWithoutSynchronization(HTMLNames::hrefAttr);
    if (href.isNull())
        return nullptr;

    Document& document = this->document();
    URL url = document.completeURL(href);
    if (!url.isValid())
        return nullptr;

    if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(url, document.baseURL())) {
        outAnchorName = url.fragmentIdentifier().toString();
        return document.findAnchor(outAnchorName);
    }

    return nullptr;
}

ExceptionOr<Ref<WebAnimation>> Element::animate(JSC::JSGlobalObject& lexicalGlobalObject, JSC::Strong<JSC::JSObject>&& keyframes, std::optional<std::variant<double, KeyframeAnimationOptions>>&& options)
{
    String id = emptyString();
    std::optional<RefPtr<AnimationTimeline>> timeline;
    std::variant<FramesPerSecond, AnimationFrameRatePreset> frameRate = AnimationFrameRatePreset::Auto;
    std::optional<std::variant<double, KeyframeEffectOptions>> keyframeEffectOptions;
    if (options) {
        auto optionsValue = options.value();
        std::variant<double, KeyframeEffectOptions> keyframeEffectOptionsVariant;
        if (std::holds_alternative<double>(optionsValue))
            keyframeEffectOptionsVariant = std::get<double>(optionsValue);
        else {
            auto keyframeEffectOptions = std::get<KeyframeAnimationOptions>(optionsValue);
            id = keyframeEffectOptions.id;
            frameRate = keyframeEffectOptions.frameRate;
            timeline = keyframeEffectOptions.timeline;
            keyframeEffectOptionsVariant = WTFMove(keyframeEffectOptions);
        }
        keyframeEffectOptions = keyframeEffectOptionsVariant;
    }

    auto keyframeEffectResult = KeyframeEffect::create(lexicalGlobalObject, document(), this, WTFMove(keyframes), WTFMove(keyframeEffectOptions));
    if (keyframeEffectResult.hasException())
        return keyframeEffectResult.releaseException();

    auto animation = WebAnimation::create(document(), &keyframeEffectResult.returnValue().get());
    animation->setId(id);
    if (timeline)
        animation->setTimeline(timeline->get());
    animation->setBindingsFrameRate(WTFMove(frameRate));

    auto animationPlayResult = animation->play();
    if (animationPlayResult.hasException())
        return animationPlayResult.releaseException();

    return animation;
}

Vector<RefPtr<WebAnimation>> Element::getAnimations(std::optional<GetAnimationsOptions> options)
{
    // If we are to return animations in the subtree, we can get all of the document's animations and filter
    // animations targeting that are not registered on this element, one of its pseudo elements or a child's
    // pseudo element.
    if (options && options->subtree) {
        return document().matchingAnimations([&] (Element& target) -> bool {
            return contains(&target);
        });
    }

    // For the list of animations to be current, we need to account for any pending CSS changes,
    // such as updates to CSS Animations and CSS Transitions. This requires updating layout as
    // well since resolving layout-dependent media queries could yield animations.
    // FIXME: We might be able to use ComputedStyleExtractor which is more optimized.
    if (RefPtr owner = document().ownerElement())
        owner->document().updateLayout();
    document().updateStyleIfNeeded();

    Vector<RefPtr<WebAnimation>> animations;
    if (auto* effectStack = keyframeEffectStack(PseudoId::None)) {
        for (auto& effect : effectStack->sortedEffects()) {
            if (effect->animation()->isRelevant())
                animations.append(effect->animation());
        }
    }
    return animations;
}

static WeakHashMap<Element, ElementIdentifier>& elementIdentifiersMap()
{
    static MainThreadNeverDestroyed<WeakHashMap<Element, ElementIdentifier>> map;
    return map;
}

ElementIdentifier Element::identifier() const
{
    return elementIdentifiersMap().ensure(*this, [] { return ElementIdentifier::generate(); }).iterator->value;
}

Element* Element::fromIdentifier(ElementIdentifier identifier)
{
    for (auto [element, elementIdentifier] : elementIdentifiersMap()) {
        if (elementIdentifier == identifier)
            return &element;
    }
    return nullptr;
}

#if ENABLE(CSS_TYPED_OM)

StylePropertyMap* Element::attributeStyleMap()
{
    if (!hasRareData())
        return nullptr;
    return elementRareData()->attributeStyleMap();
}

void Element::setAttributeStyleMap(Ref<StylePropertyMap>&& map)
{
    ensureElementRareData().setAttributeStyleMap(WTFMove(map));
}

StylePropertyMapReadOnly* Element::computedStyleMap()
{
    auto& rareData = ensureElementRareData();
    if (auto* map = rareData.computedStyleMap())
        return map;

    auto map = ComputedStylePropertyMapReadOnly::create(*this);
    rareData.setComputedStyleMap(WTFMove(map));
    return rareData.computedStyleMap();
}

#endif

} // namespace WebCore
