diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp index 8f5b8de75cab..60d847905069 100644 --- a/Source/WebCore/dom/Element.cpp +++ b/Source/WebCore/dom/Element.cpp @@ -2424,6 +2424,11 @@ void Element::invalidateStyleAndRenderersForSubtree() Node::invalidateStyle(Style::Validity::SubtreeInvalid, Style::InvalidationMode::RebuildRenderer); } +void Element::invalidateRenderer() +{ + Node::invalidateStyle(Style::Validity::Valid, Style::InvalidationMode::RebuildRenderer); +} + void Element::invalidateStyleInternal() { Node::invalidateStyle(Style::Validity::ElementInvalid); diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h index 39a2a611dbad..79776b745115 100644 --- a/Source/WebCore/dom/Element.h +++ b/Source/WebCore/dom/Element.h @@ -696,6 +696,7 @@ class Element : public ContainerNode { // custom (not style based) renderers. This is expensive and should be avoided. // Elements newly added to the tree are also in this state. void invalidateStyleAndRenderersForSubtree(); + void invalidateRenderer(); void invalidateStyleInternal(); void invalidateStyleForAnimation(); diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp index 9099c46df34f..c725ff84c14d 100644 --- a/Source/WebCore/dom/Node.cpp +++ b/Source/WebCore/dom/Node.cpp @@ -966,7 +966,8 @@ void Node::invalidateStyle(Style::Validity validity, Style::InvalidationMode mod if (document().inRenderTreeUpdate()) return; - setNodeFlag(NodeFlag::IsComputedStyleInvalidFlag); + if (validity != Style::Validity::Valid) + setNodeFlag(NodeFlag::IsComputedStyleInvalidFlag); bool markAncestors = styleValidity() == Style::Validity::Valid || mode == Style::InvalidationMode::InsertedIntoAncestor; diff --git a/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp b/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp index 2a332d464f3a..acb628ee0fd8 100644 --- a/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp +++ b/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp @@ -83,7 +83,7 @@ RenderTreeUpdater::RenderTreeUpdater(Document& document, Style::PostResolutionCa RenderTreeUpdater::~RenderTreeUpdater() = default; -static Element* findRenderingAncestor(ContainerNode& node) +static Element* findRenderingAncestor(Node& node) { for (auto& ancestor : composedTreeAncestors(node)) { if (ancestor.renderer()) @@ -633,13 +633,27 @@ void RenderTreeUpdater::updateRenderViewStyle() m_document.renderView()->setStyle(RenderStyle::clone(*m_styleUpdate->initialContainingBlockUpdate())); } +static void invalidateRebuildRootIfNeeded(Node& node) +{ + auto* ancestor = findRenderingAncestor(node); + if (!ancestor) + return; + if (!RenderTreeBuilder::isRebuildRootForChildren(*ancestor->renderer())) + return; + ancestor->invalidateRenderer(); +} + void RenderTreeUpdater::tearDownRenderers(Element& root) { + if (!root.renderer() && !root.hasDisplayContents()) + return; auto* view = root.document().renderView(); if (!view) return; + RenderTreeBuilder builder(*view); tearDownRenderers(root, TeardownType::Full, builder); + invalidateRebuildRootIfNeeded(root); } void RenderTreeUpdater::tearDownRenderersAfterSlotChange(Element& host) @@ -650,8 +664,10 @@ void RenderTreeUpdater::tearDownRenderersAfterSlotChange(Element& host) auto* view = host.document().renderView(); if (!view) return; + RenderTreeBuilder builder(*view); tearDownRenderers(host, TeardownType::FullAfterSlotChange, builder); + invalidateRebuildRootIfNeeded(host); } void RenderTreeUpdater::tearDownRenderer(Text& text) @@ -659,8 +675,10 @@ void RenderTreeUpdater::tearDownRenderer(Text& text) auto* view = text.document().renderView(); if (!view) return; + RenderTreeBuilder builder(*view); tearDownTextRenderer(text, builder); + invalidateRebuildRootIfNeeded(text); } void RenderTreeUpdater::tearDownRenderers(Element& root, TeardownType teardownType, RenderTreeBuilder& builder) diff --git a/Source/WebCore/style/StyleTreeResolver.cpp b/Source/WebCore/style/StyleTreeResolver.cpp index 2d9bfa9c4fb1..1121765ad113 100644 --- a/Source/WebCore/style/StyleTreeResolver.cpp +++ b/Source/WebCore/style/StyleTreeResolver.cpp @@ -232,6 +232,13 @@ auto TreeResolver::resolveElement(Element& element, const RenderStyle* existingS if (!element.rendererIsEverNeeded() && !element.hasDisplayContents()) return { }; + if (resolutionType == ResolutionType::RebuildUsingExisting) { + return { + ElementUpdate { RenderStyle::clonePtr(*existingStyle), Change::Renderer }, + DescendantsToResolve::RebuildAllUsingExisting + }; + } + auto resolutionContext = makeResolutionContext(); Styleable styleable { element, PseudoId::None }; @@ -743,15 +750,21 @@ auto TreeResolver::determineResolutionType(const Element& element, const RenderS return validity; }(); - if (combinedValidity == Validity::AnimationInvalid && parentDescendantsToResolve == DescendantsToResolve::None) - return ResolutionType::AnimationOnly; + if (parentDescendantsToResolve == DescendantsToResolve::None) { + if (combinedValidity == Validity::AnimationInvalid) + return ResolutionType::AnimationOnly; + if (combinedValidity == Validity::Valid && element.hasInvalidRenderer()) + return existingStyle ? ResolutionType::RebuildUsingExisting : ResolutionType::Full; + } - if (combinedValidity != Validity::Valid) + if (combinedValidity > Validity::Valid) return ResolutionType::Full; switch (parentDescendantsToResolve) { case DescendantsToResolve::None: return { }; + case DescendantsToResolve::RebuildAllUsingExisting: + return existingStyle ? ResolutionType::RebuildUsingExisting : ResolutionType::Full; case DescendantsToResolve::Children: if (parentChange == Change::FastPathInherited) { if (existingStyle && !existingStyle->disallowsFastPathInheritance()) @@ -809,6 +822,7 @@ void TreeResolver::resetDescendantStyleRelations(Element& element, DescendantsTo { switch (descendantsToResolve) { case DescendantsToResolve::None: + case DescendantsToResolve::RebuildAllUsingExisting: case DescendantsToResolve::ChildrenWithExplicitInherit: break; case DescendantsToResolve::Children: diff --git a/Source/WebCore/style/StyleTreeResolver.h b/Source/WebCore/style/StyleTreeResolver.h index d59b2fa1701d..15d9e9063d89 100644 --- a/Source/WebCore/style/StyleTreeResolver.h +++ b/Source/WebCore/style/StyleTreeResolver.h @@ -60,7 +60,7 @@ class TreeResolver { bool hasUnresolvedQueryContainers() const { return m_hasUnresolvedQueryContainers; } private: - enum class ResolutionType : uint8_t { AnimationOnly, FastPathInherit, Full }; + enum class ResolutionType : uint8_t { RebuildUsingExisting, AnimationOnly, FastPathInherit, Full }; ResolvedStyle styleForStyleable(const Styleable&, ResolutionType, const ResolutionContext&); void resolveComposedTree(); @@ -68,7 +68,7 @@ class TreeResolver { const RenderStyle* existingStyle(const Element&); enum class QueryContainerAction : uint8_t { None, Resolve, Continue }; - enum class DescendantsToResolve : uint8_t { None, ChildrenWithExplicitInherit, Children, All }; + enum class DescendantsToResolve : uint8_t { None, RebuildAllUsingExisting, ChildrenWithExplicitInherit, Children, All }; QueryContainerAction updateStateForQueryContainer(Element&, const RenderStyle*, Change&, DescendantsToResolve&);