/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005-2019 Apple Inc. All rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2012, 2013 Google Inc. All rights reserved.
 * Copyright (C) 2014, 2020, 2022 Igalia S.L.
 *
 * 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 "StyleAdjuster.h"

#include "CSSFontSelector.h"
#include "DOMTokenList.h"
#include "DOMWindow.h"
#include "ElementInlines.h"
#include "EventNames.h"
#include "FrameView.h"
#include "HTMLDialogElement.h"
#include "HTMLDivElement.h"
#include "HTMLInputElement.h"
#include "HTMLMarqueeElement.h"
#include "HTMLNames.h"
#include "HTMLSlotElement.h"
#include "HTMLTableElement.h"
#include "HTMLTextAreaElement.h"
#include "HTMLVideoElement.h"
#include "MathMLElement.h"
#include "ModalContainerObserver.h"
#include "Page.h"
#include "Quirks.h"
#include "RenderBox.h"
#include "RenderStyle.h"
#include "RenderTheme.h"
#include "RuntimeEnabledFeatures.h"
#include "SVGElement.h"
#include "SVGGraphicsElement.h"
#include "SVGNames.h"
#include "SVGURIReference.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "Text.h"
#include "WebAnimationTypes.h"
#include <wtf/RobinHoodHashSet.h>

namespace WebCore {
namespace Style {

using namespace HTMLNames;

Adjuster::Adjuster(const Document& document, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle, const Element* element)
    : m_document(document)
    , m_parentStyle(parentStyle)
    , m_parentBoxStyle(parentBoxStyle ? *parentBoxStyle : m_parentStyle)
    , m_element(element)
{
}

static void addIntrinsicMargins(RenderStyle& style)
{
    // Intrinsic margin value.
    const int intrinsicMargin = clampToInteger(2 * style.effectiveZoom());

    // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
    // FIXME: Using "hasQuirk" to decide the margin wasn't set is kind of lame.
    if (style.width().isIntrinsicOrAuto()) {
        if (style.marginLeft().hasQuirk())
            style.setMarginLeft(Length(intrinsicMargin, LengthType::Fixed));
        if (style.marginRight().hasQuirk())
            style.setMarginRight(Length(intrinsicMargin, LengthType::Fixed));
    }

    if (style.height().isAuto()) {
        if (style.marginTop().hasQuirk())
            style.setMarginTop(Length(intrinsicMargin, LengthType::Fixed));
        if (style.marginBottom().hasQuirk())
            style.setMarginBottom(Length(intrinsicMargin, LengthType::Fixed));
    }
}

static DisplayType equivalentBlockDisplay(const RenderStyle& style, const Document& document)
{
    switch (auto display = style.display()) {
    case DisplayType::Block:
    case DisplayType::Table:
    case DisplayType::Box:
    case DisplayType::Flex:
    case DisplayType::Grid:
    case DisplayType::FlowRoot:
        return display;

    case DisplayType::ListItem:
        // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
        if (document.inQuirksMode() && style.isFloating())
            return DisplayType::Block;
        return display;
    case DisplayType::InlineTable:
        return DisplayType::Table;
    case DisplayType::InlineBox:
        return DisplayType::Box;
    case DisplayType::InlineFlex:
        return DisplayType::Flex;
    case DisplayType::InlineGrid:
        return DisplayType::Grid;

    case DisplayType::Inline:
    case DisplayType::InlineBlock:
    case DisplayType::TableRowGroup:
    case DisplayType::TableHeaderGroup:
    case DisplayType::TableFooterGroup:
    case DisplayType::TableRow:
    case DisplayType::TableColumnGroup:
    case DisplayType::TableColumn:
    case DisplayType::TableCell:
    case DisplayType::TableCaption:
        return DisplayType::Block;
    case DisplayType::Contents:
        ASSERT_NOT_REACHED();
        return DisplayType::Contents;
    case DisplayType::None:
        ASSERT_NOT_REACHED();
        return DisplayType::None;
    }
    ASSERT_NOT_REACHED();
    return DisplayType::Block;
}

static bool shouldInheritTextDecorationsInEffect(const RenderStyle& style, const Element* element)
{
    if (style.isFloating() || style.hasOutOfFlowPosition())
        return false;

    auto isAtUserAgentShadowBoundary = [&] {
        if (!element)
            return false;
        auto* parentNode = element->parentNode();
        return parentNode && parentNode->isUserAgentShadowRoot();
    }();

    // There is no other good way to prevent decorations from affecting user agent shadow trees.
    if (isAtUserAgentShadowBoundary)
        return false;

    switch (style.display()) {
    case DisplayType::Table:
    case DisplayType::InlineTable:
    case DisplayType::InlineBlock:
    case DisplayType::InlineBox:
        return false;
    default:
        break;
    };

    return true;
}

static bool isScrollableOverflow(Overflow overflow)
{
    return overflow == Overflow::Scroll || overflow == Overflow::Auto;
}

static OptionSet<TouchAction> computeEffectiveTouchActions(const RenderStyle& style, OptionSet<TouchAction> effectiveTouchActions)
{
    // https://w3c.github.io/pointerevents/#determining-supported-touch-behavior
    // "A touch behavior is supported if it conforms to the touch-action property of each element between
    // the hit tested element and its nearest ancestor with the default touch behavior (including both the
    // hit tested element and the element with the default touch behavior)."

    bool hasDefaultTouchBehavior = isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY());
    if (hasDefaultTouchBehavior)
        effectiveTouchActions = RenderStyle::initialTouchActions();

    auto touchActions = style.touchActions();
    if (touchActions == RenderStyle::initialTouchActions())
        return effectiveTouchActions;

    if (effectiveTouchActions.contains(TouchAction::None))
        return { TouchAction::None };

    if (effectiveTouchActions.containsAny({ TouchAction::Auto, TouchAction::Manipulation }))
        return touchActions;

    if (touchActions.containsAny({ TouchAction::Auto, TouchAction::Manipulation }))
        return effectiveTouchActions;

    auto sharedTouchActions = effectiveTouchActions & touchActions;
    if (sharedTouchActions.isEmpty())
        return { TouchAction::None };

    return sharedTouchActions;
}

void Adjuster::adjustEventListenerRegionTypesForRootStyle(RenderStyle& rootStyle, const Document& document)
{
    auto regionTypes = computeEventListenerRegionTypes(document, rootStyle, document, { });
    if (auto* window = document.domWindow())
        regionTypes.add(computeEventListenerRegionTypes(document, rootStyle, *window, { }));

    rootStyle.setEventListenerRegionTypes(regionTypes);
}

OptionSet<EventListenerRegionType> Adjuster::computeEventListenerRegionTypes(const Document& document, const RenderStyle& style, const EventTarget& eventTarget, OptionSet<EventListenerRegionType> parentTypes)
{
    auto types = parentTypes;

#if ENABLE(WHEEL_EVENT_REGIONS)
    auto findListeners = [&](auto& eventName, auto type, auto nonPassiveType) {
        auto* eventListenerVector = eventTarget.eventTargetData()->eventListenerMap.find(eventName);
        if (!eventListenerVector)
            return;

        types.add(type);

        auto isPassiveOnly = [&] {
            for (auto& listener : *eventListenerVector) {
                if (!listener->isPassive())
                    return false;
            }
            return true;
        }();

        if (!isPassiveOnly)
            types.add(nonPassiveType);
    };

    if (eventTarget.hasEventListeners()) {
        findListeners(eventNames().wheelEvent, EventListenerRegionType::Wheel, EventListenerRegionType::NonPassiveWheel);
        findListeners(eventNames().mousewheelEvent, EventListenerRegionType::Wheel, EventListenerRegionType::NonPassiveWheel);
    }
#endif

#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
    if (document.page() && document.page()->shouldBuildInteractionRegions() && eventTarget.isNode()) {
        const auto& node = downcast<Node>(eventTarget);
        if (node.willRespondToMouseClickEventsWithEditability(node.computeEditabilityForMouseClickEvents(&style)))
            types.add(EventListenerRegionType::MouseClick);
    }
#else
    UNUSED_PARAM(document);
    UNUSED_PARAM(style);
#endif

#if !ENABLE(WHEEL_EVENT_REGIONS) && !ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
    UNUSED_PARAM(eventTarget);
#endif

    return types;
}

void Adjuster::adjust(RenderStyle& style, const RenderStyle* userAgentAppearanceStyle) const
{
    if (style.display() == DisplayType::Contents)
        adjustDisplayContentsStyle(style);

    if (style.display() != DisplayType::None && style.display() != DisplayType::Contents) {
        if (m_element) {
            // If we have a <td> that specifies a float property, in quirks mode we just drop the float
            // property.
            // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
            // these tags to retain their display types.
            if (m_document.inQuirksMode()) {
                if (m_element->hasTagName(tdTag)) {
                    style.setEffectiveDisplay(DisplayType::TableCell);
                    style.setFloating(Float::None);
                } else if (is<HTMLTableElement>(*m_element))
                    style.setEffectiveDisplay(style.isDisplayInlineType() ? DisplayType::InlineTable : DisplayType::Table);
            }

            if (m_element->hasTagName(tdTag) || m_element->hasTagName(thTag)) {
                if (style.whiteSpace() == WhiteSpace::KHTMLNoWrap) {
                    // Figure out if we are really nowrapping or if we should just
                    // use normal instead. If the width of the cell is fixed, then
                    // we don't actually use WhiteSpace::NoWrap.
                    if (style.width().isFixed())
                        style.setWhiteSpace(WhiteSpace::Normal);
                    else
                        style.setWhiteSpace(WhiteSpace::NoWrap);
                }
            }

            // Tables never support the -webkit-* values for text-align and will reset back to the default.
            if (is<HTMLTableElement>(*m_element) && (style.textAlign() == TextAlignMode::WebKitLeft || style.textAlign() == TextAlignMode::WebKitCenter || style.textAlign() == TextAlignMode::WebKitRight))
                style.setTextAlign(TextAlignMode::Start);

            // Frames and framesets never honor position:relative or position:absolute. This is necessary to
            // fix a crash where a site tries to position these objects. They also never honor display.
            if (m_element->hasTagName(frameTag) || m_element->hasTagName(framesetTag)) {
                style.setPosition(PositionType::Static);
                style.setEffectiveDisplay(DisplayType::Block);
            }

            // Ruby text does not support float or position. This might change with evolution of the specification.
            if (m_element->hasTagName(rtTag)) {
                style.setPosition(PositionType::Static);
                style.setFloating(Float::None);
            }

            if (m_element->hasTagName(legendTag))
                style.setEffectiveDisplay(DisplayType::Block);
        }

        // Top layer elements are always position: absolute; unless the position is set to fixed.
        // https://fullscreen.spec.whatwg.org/#new-stacking-layer
        if (style.position() != PositionType::Absolute && style.position() != PositionType::Fixed && isInTopLayerOrBackdrop(style, m_element))
            style.setPosition(PositionType::Absolute);

        // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
        if (style.hasOutOfFlowPosition() || style.isFloating() || (m_element && m_document.documentElement() == m_element))
            style.setEffectiveDisplay(equivalentBlockDisplay(style, m_document));

        // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
        // clear how that should work.
        if (style.display() == DisplayType::Inline && style.styleType() == PseudoId::None && style.writingMode() != m_parentStyle.writingMode())
            style.setEffectiveDisplay(DisplayType::InlineBlock);

        // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
        // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
        // on some sites).
        if ((style.display() == DisplayType::TableHeaderGroup || style.display() == DisplayType::TableRowGroup
            || style.display() == DisplayType::TableFooterGroup || style.display() == DisplayType::TableRow)
            && style.position() == PositionType::Relative)
            style.setPosition(PositionType::Static);

        // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
        // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
        if (style.display() == DisplayType::TableColumn || style.display() == DisplayType::TableColumnGroup || style.display() == DisplayType::TableFooterGroup
            || style.display() == DisplayType::TableHeaderGroup || style.display() == DisplayType::TableRow || style.display() == DisplayType::TableRowGroup
            || style.display() == DisplayType::TableCell)
            style.setWritingMode(m_parentStyle.writingMode());

        // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
        // of block-flow to anything other than WritingMode::TopToBottom.
        // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
        if (style.writingMode() != WritingMode::TopToBottom && (style.display() == DisplayType::Box || style.display() == DisplayType::InlineBox))
            style.setWritingMode(WritingMode::TopToBottom);

        // https://www.w3.org/TR/css-display/#transformations
        // "A parent with a grid or flex display value blockifies the box’s display type."
        if (m_parentBoxStyle.isDisplayFlexibleOrGridBox()) {
            style.setFloating(Float::None);
            style.setEffectiveDisplay(equivalentBlockDisplay(style, m_document));
        }
    }

    // Make sure our z-index value is only applied if the object is positioned.
    if (style.hasAutoSpecifiedZIndex() || (style.position() == PositionType::Static && !m_parentBoxStyle.isDisplayFlexibleOrGridBox()))
        style.setHasAutoUsedZIndex();
    else
        style.setUsedZIndex(style.specifiedZIndex());

    // For SVG compatibility purposes we have to consider the 'animatedLocalTransform' besides the RenderStyle to query
    // if an element has a transform. SVG transforms are not stored on the RenderStyle, and thus we need a special case here.
    auto hasTransformRelatedProperty = [](const RenderStyle& style, const Element* element) {
        if (style.hasTransformRelatedProperty())
            return true;

#if ENABLE(LAYER_BASED_SVG_ENGINE)
        if (element && element->document().settings().layerBasedSVGEngineEnabled() && is<SVGGraphicsElement>(element))
            return !downcast<SVGGraphicsElement>(*element).animatedLocalTransform().isIdentity();
#else
        UNUSED_PARAM(element);
#endif

        return false;
    };

    // Auto z-index becomes 0 for the root element and transparent objects. This prevents
    // cases where objects that should be blended as a single unit end up with a non-transparent
    // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
    if (style.hasAutoUsedZIndex()) {
        if ((m_element && m_document.documentElement() == m_element)
            || style.hasOpacity()
            || hasTransformRelatedProperty(style, m_element)
            || style.hasMask()
            || style.clipPath()
            || style.boxReflect()
            || style.hasFilter()
#if ENABLE(FILTERS_LEVEL_2)
            || style.hasBackdropFilter()
#endif
            || style.hasBlendMode()
            || style.hasIsolation()
            || style.position() == PositionType::Sticky
            || style.position() == PositionType::Fixed
            || style.willChangeCreatesStackingContext()
            || isInTopLayerOrBackdrop(style, m_element))
            style.setUsedZIndex(0);
    }

    if (m_element) {
        // Textarea considers overflow visible as auto.
        if (is<HTMLTextAreaElement>(*m_element)) {
            style.setOverflowX(style.overflowX() == Overflow::Visible ? Overflow::Auto : style.overflowX());
            style.setOverflowY(style.overflowY() == Overflow::Visible ? Overflow::Auto : style.overflowY());
        }

        if (is<HTMLInputElement>(*m_element) && downcast<HTMLInputElement>(*m_element).isPasswordField())
            style.setTextSecurity(style.inputSecurity() == InputSecurity::Auto ? TextSecurity::Disc : TextSecurity::None);

        // Disallow -webkit-user-modify on :pseudo and ::pseudo elements.
        if (!m_element->shadowPseudoId().isNull())
            style.setUserModify(UserModify::ReadOnly);

        if (is<HTMLMarqueeElement>(*m_element)) {
            // For now, <marquee> requires an overflow clip to work properly.
            style.setOverflowX(Overflow::Hidden);
            style.setOverflowY(Overflow::Hidden);

            bool isVertical = style.marqueeDirection() == MarqueeDirection::Up || style.marqueeDirection() == MarqueeDirection::Down;
            // Make horizontal marquees not wrap.
            if (!isVertical) {
                style.setWhiteSpace(WhiteSpace::NoWrap);
                style.setTextAlign(TextAlignMode::Start);
            }
            // Apparently this is the expected legacy behavior.
            if (isVertical && style.height().isAuto())
                style.setHeight(Length(200, LengthType::Fixed));
        }
    }

    if (shouldInheritTextDecorationsInEffect(style, m_element))
        style.addToTextDecorationsInEffect(style.textDecorationLine());
    else
        style.setTextDecorationsInEffect(style.textDecorationLine());

    auto overflowReplacement = [] (Overflow overflow, Overflow overflowInOtherDimension) -> std::optional<Overflow> {
        if (overflow != Overflow::Visible && overflow != Overflow::Clip) {
            if (overflowInOtherDimension == Overflow::Visible)
                return Overflow::Auto;
            if (overflowInOtherDimension == Overflow::Clip)
                return Overflow::Hidden;
        }
        return std::nullopt;
    };

    // If either overflow value is not visible, change to auto. Similarly if either overflow
    // value is not clip, change to hidden.
    // FIXME: Once we implement pagination controls, overflow-x should default to hidden
    // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
    // default to auto so we can at least scroll through the pages.
    if (auto replacement = overflowReplacement(style.overflowY(), style.overflowX()))
        style.setOverflowX(*replacement);
    else if (auto replacement = overflowReplacement(style.overflowX(), style.overflowY()))
        style.setOverflowY(*replacement);

    // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
    // styles are specified on a root element, then they will be incorporated in
    // Style::createForm_document.
    if ((style.overflowY() == Overflow::PagedX || style.overflowY() == Overflow::PagedY) && !(m_element && (m_element->hasTagName(htmlTag) || m_element->hasTagName(bodyTag))))
        style.setColumnStylesFromPaginationMode(WebCore::paginationModeForRenderStyle(style));

    // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
    // FIXME: Eventually table sections will support auto and scroll.
    if (style.display() == DisplayType::Table || style.display() == DisplayType::InlineTable
        || style.display() == DisplayType::TableRowGroup || style.display() == DisplayType::TableRow) {
        if (style.overflowX() != Overflow::Visible && style.overflowX() != Overflow::Hidden)
            style.setOverflowX(Overflow::Visible);
        if (style.overflowY() != Overflow::Visible && style.overflowY() != Overflow::Hidden)
            style.setOverflowY(Overflow::Visible);
    }

#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
    // Touch overflow scrolling creates a stacking context.
    if (style.hasAutoUsedZIndex() && style.useTouchOverflowScrolling() && (isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY())))
        style.setUsedZIndex(0);
#endif

    // contain: layout creates a stacking context.
    if (style.hasAutoUsedZIndex() && style.containsLayout())
        style.setUsedZIndex(0);

    // Cull out any useless layers and also repeat patterns into additional layers.
    style.adjustBackgroundLayers();
    style.adjustMaskLayers();

    // Do the same for animations and transitions.
    style.adjustAnimations();
    style.adjustTransitions();

    // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
    // alter fonts and heights/widths.
    if (is<HTMLFormControlElement>(m_element) && style.computedFontPixelSize() >= 11) {
        // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
        // so we have to treat all image buttons as though they were explicitly sized.
        if (!is<HTMLInputElement>(*m_element) || !downcast<HTMLInputElement>(*m_element).isImageButton())
            addIntrinsicMargins(style);
    }

    // Let the theme also have a crack at adjusting the style.
    if (style.hasAppearance())
        RenderTheme::singleton().adjustStyle(style, m_element, userAgentAppearanceStyle);

    // If we have first-letter pseudo style, do not share this style.
    if (style.hasPseudoStyle(PseudoId::FirstLetter))
        style.setUnique();

    if (style.preserves3D()) {
        bool forceToFlat = style.overflowX() != Overflow::Visible
            || style.hasOpacity()
            || style.overflowY() != Overflow::Visible
            || style.hasClip()
            || style.clipPath()
            || style.hasFilter()
            || style.hasIsolation()
            || style.hasMask()
#if ENABLE(FILTERS_LEVEL_2)
            || style.hasBackdropFilter()
#endif
            || style.hasBlendMode();
        style.setTransformStyleForcedToFlat(forceToFlat);
    }

    if (is<SVGElement>(m_element))
        adjustSVGElementStyle(style, downcast<SVGElement>(*m_element));

    // If the inherited value of justify-items includes the 'legacy' keyword (plus 'left', 'right' or
    // 'center'), 'legacy' computes to the the inherited value. Otherwise, 'auto' computes to 'normal'.
    if (m_parentBoxStyle.justifyItems().positionType() == ItemPositionType::Legacy && style.justifyItems().position() == ItemPosition::Legacy)
        style.setJustifyItems(m_parentBoxStyle.justifyItems());

    style.setEffectiveTouchActions(computeEffectiveTouchActions(style, m_parentStyle.effectiveTouchActions()));

    // Counterparts in Element::addToTopLayer/removeFromTopLayer & SharingResolver::canShareStyleWithElement need to match!
    auto hasInertAttribute = [this] (const Element* element) -> bool {
        return m_document.settings().inertAttributeEnabled() && is<HTMLElement>(element) && element->hasAttributeWithoutSynchronization(HTMLNames::inertAttr);
    };
    auto isInertSubtreeRoot = [this, hasInertAttribute] (const Element* element) -> bool {
        if (m_document.activeModalDialog() && element == m_document.documentElement())
            return true;
        if (hasInertAttribute(element))
            return true;
        return false;
    };
    if (isInertSubtreeRoot(m_element))
        style.setEffectiveInert(true);

    if (m_element) {
        // Make sure the active dialog is interactable when the whole document is blocked by the modal dialog
        if (m_element == m_document.activeModalDialog() && !hasInertAttribute(m_element))
            style.setEffectiveInert(false);

        style.setEventListenerRegionTypes(computeEventListenerRegionTypes(m_document, style, *m_element, m_parentStyle.eventListenerRegionTypes()));

#if ENABLE(TEXT_AUTOSIZING)
        if (m_document.settings().textAutosizingUsesIdempotentMode())
            adjustForTextAutosizing(style, *m_element);
#endif

        if (auto observer = m_element->document().modalContainerObserverIfExists()) {
            if (observer->shouldHide(*m_element))
                style.setDisplay(DisplayType::None);
            if (observer->shouldMakeVerticallyScrollable(*m_element))
                style.setOverflowY(Overflow::Auto);
        }
    }

    adjustForSiteSpecificQuirks(style);
}

static bool hasEffectiveDisplayNoneForDisplayContents(const Element& element)
{
    // https://drafts.csswg.org/css-display-3/#unbox-html
    static NeverDestroyed<MemoryCompactLookupOnlyRobinHoodHashSet<AtomString>> tagNames = [] {
        static const HTMLQualifiedName* const tagList[] = {
            &brTag.get(),
            &wbrTag.get(),
            &meterTag.get(),
            &appletTag.get(),
            &progressTag.get(),
            &canvasTag.get(),
            &embedTag.get(),
            &objectTag.get(),
            &audioTag.get(),
            &iframeTag.get(),
            &imgTag.get(),
            &videoTag.get(),
            &frameTag.get(),
            &framesetTag.get(),
            &inputTag.get(),
            &textareaTag.get(),
            &selectTag.get(),
        };
        MemoryCompactLookupOnlyRobinHoodHashSet<AtomString> set;
        set.reserveInitialCapacity(sizeof(tagList));
        for (auto& name : tagList)
            set.add(name->localName());
        return set;
    }();

    // https://drafts.csswg.org/css-display-3/#unbox-svg
    // FIXME: <g>, <use> and <tspan> have special (?) behavior for display:contents in the current draft spec.
    if (is<SVGElement>(element))
        return true;
#if ENABLE(MATHML)
    // Not sure MathML code can handle it.
    if (is<MathMLElement>(element))
        return true;
#endif // ENABLE(MATHML)
    if (!is<HTMLElement>(element))
        return false;
    return tagNames.get().contains(element.localName());
}

void Adjuster::adjustDisplayContentsStyle(RenderStyle& style) const
{
    bool isInTopLayer = isInTopLayerOrBackdrop(style, m_element);
    if (isInTopLayer || m_document.documentElement() == m_element) {
        style.setEffectiveDisplay(DisplayType::Block);
        return;
    }

    if (!m_element && style.styleType() != PseudoId::Before && style.styleType() != PseudoId::After) {
        style.setEffectiveDisplay(DisplayType::None);
        return;
    }

    if (m_element && hasEffectiveDisplayNoneForDisplayContents(*m_element))
        style.setEffectiveDisplay(DisplayType::None);
}

void Adjuster::adjustSVGElementStyle(RenderStyle& style, const SVGElement& svgElement)
{
    // Only the root <svg> element in an SVG document fragment tree honors css position
    auto isPositioningAllowed = svgElement.hasTagName(SVGNames::svgTag) && svgElement.parentNode() && !svgElement.parentNode()->isSVGElement() && !svgElement.correspondingElement();
    if (!isPositioningAllowed)
        style.setPosition(RenderStyle::initialPosition());

#if ENABLE(LAYER_BASED_SVG_ENGINE)
    // SVG2: A new stacking context must be established at an SVG element for its descendants if:
    // - it is the root element
    // - the "z-index" property applies to the element and its computed value is an integer
    // - the element is an outermost svg element, or a "foreignObject", "image", "marker", "mask", "pattern", "symbol" or "use" element
    // - the element is an inner "svg" element and the computed value of its "overflow" property is a value other than visible
    // - the element is subject to explicit clipping:
    //   - the "clip" property applies to the element and it has a computed value other than auto
    //   - the "clip-path" property applies to the element and it has a computed value other than none
    // - the "mask" property applies to the element and it has a computed value other than none
    // - the "filter" property applies to the element and it has a computed value other than none
    // - a property defined in another specification is applied and that property is defined to establish a stacking context in SVG
    //
    // Some of the rules above were already enforced in StyleResolver::adjustRenderStyle() - for those cases assertions were added.
    if (svgElement.document().settings().layerBasedSVGEngineEnabled() && style.hasAutoUsedZIndex()) {
        // adjustRenderStyle() has already assigned a z-index of 0 if clip / filter is present or the element is the root element.
        ASSERT(!style.hasClip());
        ASSERT(!style.clipPath());
        ASSERT(!style.hasFilter());
        ASSERT(!svgElement.isOutermostSVGSVGElement());

        auto isInnerSVGElement = [] (const SVGElement& svgElement) -> bool {
            return svgElement.hasTagName(SVGNames::svgTag) && svgElement.parentNode() && is<SVGElement>(svgElement.parentNode());
        };

        if (svgElement.hasTagName(SVGNames::foreignObjectTag)
            || svgElement.hasTagName(SVGNames::imageTag)
            || svgElement.hasTagName(SVGNames::markerTag)
            || svgElement.hasTagName(SVGNames::maskTag)
            || svgElement.hasTagName(SVGNames::patternTag)
            || svgElement.hasTagName(SVGNames::symbolTag)
            || svgElement.hasTagName(SVGNames::useTag)
            || (isInnerSVGElement(svgElement) && (style.overflowX() != Overflow::Visible || style.overflowY() != Overflow::Visible))
            || style.hasPositionedMask())
        style.setUsedZIndex(0);
    }
#endif

    // (Legacy)RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
    // not be scaled again.
    if (svgElement.hasTagName(SVGNames::foreignObjectTag))
        style.setEffectiveZoom(RenderStyle::initialZoom());

    // SVG text layout code expects us to be a block-level style element.
    if ((svgElement.hasTagName(SVGNames::foreignObjectTag) || svgElement.hasTagName(SVGNames::textTag)) && style.isDisplayInlineType())
        style.setEffectiveDisplay(DisplayType::Block);
}

void Adjuster::adjustAnimatedStyle(RenderStyle& style, OptionSet<AnimationImpact> impact) const
{
    adjust(style, nullptr);

    // Set an explicit used z-index in two cases:
    // 1. When the element respects z-index, and the style has an explicit z-index set (for example, the animation
    //    itself may animate z-index).
    // 2. When we want the stacking context side-effets of explicit z-index, via forceStackingContext.
    // It's important to not clobber an existing used z-index, since an earlier animation may have set it, but we
    // may still need to update the used z-index value from the specified value.
    
    if (style.hasAutoUsedZIndex() && impact.contains(AnimationImpact::ForcesStackingContext))
        style.setUsedZIndex(0);
}

void Adjuster::adjustForSiteSpecificQuirks(RenderStyle& style) const
{
    if (!m_element)
        return;

    if (m_document.quirks().needsGMailOverflowScrollQuirk()) {
        // This turns sidebar scrollable without mouse move event.
        static MainThreadNeverDestroyed<const AtomString> roleValue("navigation"_s);
        if (style.overflowY() == Overflow::Hidden && m_element->attributeWithoutSynchronization(roleAttr) == roleValue)
            style.setOverflowY(Overflow::Auto);
    }
    if (m_document.quirks().needsYouTubeOverflowScrollQuirk()) {
        // This turns sidebar scrollable without hover.
        static MainThreadNeverDestroyed<const AtomString> idValue("guide-inner-content"_s);
        if (style.overflowY() == Overflow::Hidden && m_element->idForStyleResolution() == idValue)
            style.setOverflowY(Overflow::Auto);
    }
    if (m_document.quirks().needsWeChatScrollingQuirk()) {
        static MainThreadNeverDestroyed<const AtomString> class1("tree-select"_s);
        static MainThreadNeverDestroyed<const AtomString> class2("v-tree-select"_s);
        const auto& flexBasis = style.flexBasis();
        if (style.minHeight().isAuto()
            && style.display() == DisplayType::Flex
            && style.flexGrow() == 1
            && style.flexShrink() == 1
            && (flexBasis.isPercent() || flexBasis.isFixed())
            && flexBasis.value() == 0
            && const_cast<Element*>(m_element)->classList().contains(class1)
            && const_cast<Element*>(m_element)->classList().contains(class2))
            style.setMinHeight(Length(0, LengthType::Fixed));
    }
#if ENABLE(VIDEO)
    if (m_document.quirks().needsFullscreenDisplayNoneQuirk()) {
        if (is<HTMLDivElement>(m_element) && style.display() == DisplayType::None) {
            static MainThreadNeverDestroyed<const AtomString> instreamNativeVideoDivClass("instream-native-video--mobile"_s);
            static MainThreadNeverDestroyed<const AtomString> videoElementID("vjs_video_3_html5_api"_s);

            auto& div = downcast<HTMLDivElement>(*m_element);
            if (div.hasClass() && div.classNames().contains(instreamNativeVideoDivClass)) {
                auto* video = div.treeScope().getElementById(videoElementID);
                if (is<HTMLVideoElement>(video) && downcast<HTMLVideoElement>(*video).isFullscreen())
                    style.setEffectiveDisplay(DisplayType::Block);
            }
        }
    }
#endif
}

#if ENABLE(TEXT_AUTOSIZING)
static bool hasTextChild(const Element& element)
{
    for (auto* child = element.firstChild(); child; child = child->nextSibling()) {
        if (is<Text>(child))
            return true;
    }
    return false;
}

auto Adjuster::adjustmentForTextAutosizing(const RenderStyle& style, const Element& element) -> AdjustmentForTextAutosizing
{
    AdjustmentForTextAutosizing adjustmentForTextAutosizing;

    auto& document = element.document();
    if (!document.settings().textAutosizingEnabled()
        || !document.settings().textAutosizingUsesIdempotentMode()
        || document.settings().idempotentModeAutosizingOnlyHonorsPercentages())
        return adjustmentForTextAutosizing;

    auto newStatus = AutosizeStatus::computeStatus(style);
    if (newStatus != style.autosizeStatus())
        adjustmentForTextAutosizing.newStatus = newStatus;

    if (style.textSizeAdjust().isNone())
        return adjustmentForTextAutosizing;

    float initialScale = document.page() ? document.page()->initialScaleIgnoringContentSize() : 1;
    auto adjustLineHeightIfNeeded = [&](auto computedFontSize) {
        auto lineHeight = style.specifiedLineHeight();
        constexpr static unsigned eligibleFontSize = 12;
        if (computedFontSize * initialScale >= eligibleFontSize)
            return;

        constexpr static float boostFactor = 1.25;
        auto minimumLineHeight = boostFactor * computedFontSize;
        if (!lineHeight.isFixed() || lineHeight.value() >= minimumLineHeight)
            return;

        if (AutosizeStatus::probablyContainsASmallFixedNumberOfLines(style))
            return;

        adjustmentForTextAutosizing.newLineHeight = minimumLineHeight;
    };

    auto fontDescription = style.fontDescription();
    auto initialComputedFontSize = fontDescription.computedSize();
    auto specifiedFontSize = fontDescription.specifiedSize();
    bool isCandidate = style.isIdempotentTextAutosizingCandidate(newStatus);
    if (!isCandidate && WTF::areEssentiallyEqual(initialComputedFontSize, specifiedFontSize))
        return adjustmentForTextAutosizing;

    auto adjustedFontSize = AutosizeStatus::idempotentTextSize(fontDescription.specifiedSize(), initialScale);
    if (isCandidate && WTF::areEssentiallyEqual(initialComputedFontSize, adjustedFontSize))
        return adjustmentForTextAutosizing;

    if (!hasTextChild(element))
        return adjustmentForTextAutosizing;

    adjustmentForTextAutosizing.newFontSize = isCandidate ? adjustedFontSize : specifiedFontSize;

    // FIXME: We should restore computed line height to its original value in the case where the element is not
    // an idempotent text autosizing candidate; otherwise, if an element that is a text autosizing candidate contains
    // children which are not autosized, the non-autosized content will end up with a boosted line height.
    if (isCandidate)
        adjustLineHeightIfNeeded(adjustedFontSize);

    return adjustmentForTextAutosizing;
}

bool Adjuster::adjustForTextAutosizing(RenderStyle& style, const Element& element, AdjustmentForTextAutosizing adjustment)
{
    AutosizeStatus::updateStatus(style);
    if (auto newFontSize = adjustment.newFontSize) {
        auto fontDescription = style.fontDescription();
        fontDescription.setComputedSize(*newFontSize);
        style.setFontDescription(WTFMove(fontDescription));
        style.fontCascade().update(&element.document().fontSelector());
    }
    if (auto newLineHeight = adjustment.newLineHeight)
        style.setLineHeight({ *newLineHeight, LengthType::Fixed });
    if (auto newStatus = adjustment.newStatus)
        style.setAutosizeStatus(*newStatus);
    return adjustment.newFontSize || adjustment.newLineHeight;
}

bool Adjuster::adjustForTextAutosizing(RenderStyle& style, const Element& element)
{
    return adjustForTextAutosizing(style, element, adjustmentForTextAutosizing(style, element));
}
#endif

}
}
