Title: [288906] trunk
Revision
288906
Author
[email protected]
Date
2022-02-01 12:34:28 -0800 (Tue, 01 Feb 2022)

Log Message

[CSS Container Queries] Ensure query containers have valid layout before resolving the subtree
https://bugs.webkit.org/show_bug.cgi?id=235896

Reviewed by Alan Bujtas.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt:

Source/WebCore:

To resolve container queries we need to have up-to-date layout for the query containers before
style resolution advances to their descendants.

With this patch we bounce between style resolution and layout until all query containers are resolved.

* dom/Document.cpp:
(WebCore::Document::resolveStyle):

Loop style resolution/render tree update/layout until we have resolved everything.

* dom/Document.h:
(WebCore::Document::isResolvingContainerQueries const):
* page/FrameViewLayoutContext.cpp:
(WebCore::FrameViewLayoutContext::layout):
(WebCore::FrameViewLayoutContext::runOrScheduleAsynchronousTasks):

Don't run post-layout tasks when resolving query containers.

* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::resolveComposedTree):
(WebCore::Style::TreeResolver::updateQueryContainer):

Track what has been resolved.

(WebCore::Style::TreeResolver::resolve):
* style/StyleTreeResolver.h:
(WebCore::Style::TreeResolver::hasUnresolvedQueryContainers const):
* style/StyleUpdate.h:
(WebCore::Style::Update::isEmpty const):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (288905 => 288906)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-02-01 20:34:28 UTC (rev 288906)
@@ -1,3 +1,12 @@
+2022-02-01  Antti Koivisto  <[email protected]>
+
+        [CSS Container Queries] Ensure query containers have valid layout before resolving the subtree
+        https://bugs.webkit.org/show_bug.cgi?id=235896
+
+        Reviewed by Alan Bujtas.
+
+        * web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt:
+
 2022-02-01  Ada Chan  <[email protected]>
 
         [WebXR] Handle changes in XRSession's visibility state

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt (288905 => 288906)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/container-type-invalidation-expected.txt	2022-02-01 20:34:28 UTC (rev 288906)
@@ -1,4 +1,4 @@
 Test
 
-FAIL Changing the container type invalidates relevant descendants assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)"
+FAIL Changing the container type invalidates relevant descendants assert_equals: expected "rgb(0, 0, 0)" but got "rgb(0, 128, 0)"
 

Modified: trunk/Source/WebCore/ChangeLog (288905 => 288906)


--- trunk/Source/WebCore/ChangeLog	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/ChangeLog	2022-02-01 20:34:28 UTC (rev 288906)
@@ -1,3 +1,40 @@
+2022-02-01  Antti Koivisto  <[email protected]>
+
+        [CSS Container Queries] Ensure query containers have valid layout before resolving the subtree
+        https://bugs.webkit.org/show_bug.cgi?id=235896
+
+        Reviewed by Alan Bujtas.
+
+        To resolve container queries we need to have up-to-date layout for the query containers before
+        style resolution advances to their descendants.
+
+        With this patch we bounce between style resolution and layout until all query containers are resolved.
+
+        * dom/Document.cpp:
+        (WebCore::Document::resolveStyle):
+
+        Loop style resolution/render tree update/layout until we have resolved everything.
+
+        * dom/Document.h:
+        (WebCore::Document::isResolvingContainerQueries const):
+        * page/FrameViewLayoutContext.cpp:
+        (WebCore::FrameViewLayoutContext::layout):
+        (WebCore::FrameViewLayoutContext::runOrScheduleAsynchronousTasks):
+
+        Don't run post-layout tasks when resolving query containers.
+
+        * style/StyleTreeResolver.cpp:
+        (WebCore::Style::TreeResolver::resolveComposedTree):
+        (WebCore::Style::TreeResolver::updateQueryContainer):
+
+        Track what has been resolved.
+
+        (WebCore::Style::TreeResolver::resolve):
+        * style/StyleTreeResolver.h:
+        (WebCore::Style::TreeResolver::hasUnresolvedQueryContainers const):
+        * style/StyleUpdate.h:
+        (WebCore::Style::Update::isEmpty const):
+
 2022-02-01  Pablo Saavedra  <[email protected]>
 
         [GTK][WPE] Fixes for non-unified builds after r288807 and r288820

Modified: trunk/Source/WebCore/dom/Document.cpp (288905 => 288906)


--- trunk/Source/WebCore/dom/Document.cpp	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/dom/Document.cpp	2022-02-01 20:34:28 UTC (rev 288906)
@@ -2055,6 +2055,17 @@
         Style::TreeResolver resolver(*this, WTFMove(m_pendingRenderTreeTextUpdate));
         auto styleUpdate = resolver.resolve();
 
+        while (resolver.hasUnresolvedQueryContainers() && styleUpdate) {
+            SetForScope resolvingContainerQueriesScope(m_isResolvingContainerQueries, true);
+
+            updateRenderTree(WTFMove(styleUpdate));
+
+            if (frameView.layoutContext().needsLayout())
+                frameView.layoutContext().layout();
+
+            styleUpdate = resolver.resolve();
+        }
+
         m_lastStyleUpdateSizeForTesting = styleUpdate ? styleUpdate->size() : 0;
 
         setHasValidStyle();

Modified: trunk/Source/WebCore/dom/Document.h (288905 => 288906)


--- trunk/Source/WebCore/dom/Document.h	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/dom/Document.h	2022-02-01 20:34:28 UTC (rev 288906)
@@ -1345,6 +1345,7 @@
 
     bool inStyleRecalc() const { return m_inStyleRecalc; }
     bool inRenderTreeUpdate() const { return m_inRenderTreeUpdate; }
+    bool isResolvingContainerQueries() const { return m_isResolvingContainerQueries; }
     bool isResolvingTreeStyle() const { return m_isResolvingTreeStyle; }
     void setIsResolvingTreeStyle(bool);
 
@@ -2136,6 +2137,7 @@
     bool m_inStyleRecalc { false };
     bool m_inRenderTreeUpdate { false };
     bool m_isResolvingTreeStyle { false };
+    bool m_isResolvingContainerQueries { false };
 
     bool m_gotoAnchorNeededAfterStylesheetsLoad { false };
     bool m_isDNSPrefetchEnabled { false };

Modified: trunk/Source/WebCore/page/FrameViewLayoutContext.cpp (288905 => 288906)


--- trunk/Source/WebCore/page/FrameViewLayoutContext.cpp	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/page/FrameViewLayoutContext.cpp	2022-02-01 20:34:28 UTC (rev 288906)
@@ -204,11 +204,14 @@
     {
         SetForScope<LayoutPhase> layoutPhase(m_layoutPhase, LayoutPhase::InPreLayout);
 
-        // If this is a new top-level layout and there are any remaining tasks from the previous layout, finish them now.
-        if (!isLayoutNested() && m_asynchronousTasksTimer.isActive() && !view().isInChildFrameWithFrameFlattening())
-            runAsynchronousTasks();
+        if (!frame().document()->isResolvingContainerQueries()) {
+            // If this is a new top-level layout and there are any remaining tasks from the previous layout, finish them now.
+            if (!isLayoutNested() && m_asynchronousTasksTimer.isActive() && !view().isInChildFrameWithFrameFlattening())
+                runAsynchronousTasks();
 
-        updateStyleForLayout();
+            updateStyleForLayout();
+        }
+
         if (view().hasOneRef())
             return;
 
@@ -268,6 +271,12 @@
     if (m_asynchronousTasksTimer.isActive())
         return;
 
+    if (frame().document()->isResolvingContainerQueries()) {
+        // We are doing layout from style resolution to resolve container queries.
+        m_asynchronousTasksTimer.startOneShot(0_s);
+        return;
+    }
+
     if (view().isInChildFrameWithFrameFlattening()) {
         // While flattening frames, we defer post layout tasks to avoid getting stuck in a cycle,
         // except updateWidgetPositions() which is required to kick off subframe layout in certain cases.

Modified: trunk/Source/WebCore/style/StyleTreeResolver.cpp (288905 => 288906)


--- trunk/Source/WebCore/style/StyleTreeResolver.cpp	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/style/StyleTreeResolver.cpp	2022-02-01 20:34:28 UTC (rev 288906)
@@ -598,8 +598,10 @@
 
         bool shouldIterateChildren = style && (element.childNeedsStyleRecalc() || descendantsToResolve != DescendantsToResolve::None);
 
-        if (shouldIterateChildren)
-            updateQueryContainer(element, *style);
+        if (shouldIterateChildren) {
+            if (updateQueryContainer(element, *style) == QueryContainerAction::Layout)
+                shouldIterateChildren = false;
+        }
 
         if (!m_didSeePendingStylesheet)
             m_didSeePendingStylesheet = hasLoadingStylesheet(m_document.styleScope(), element, !shouldIterateChildren);
@@ -619,14 +621,26 @@
     popParentsToDepth(1);
 }
 
-void TreeResolver::updateQueryContainer(const Element& element, const RenderStyle& style)
+auto TreeResolver::updateQueryContainer(Element& element, const RenderStyle& style) -> QueryContainerAction
 {
     if (style.containerType() == ContainerType::None)
-        return;
+        return QueryContainerAction::None;
 
     scope().selectorMatchingState.queryContainers.append(element);
 
-    // FIXME: Skip the subtree and ensure the container is resolved by doing a layout if needed.
+    if (m_unresolvedQueryContainers.remove(&element)) {
+        m_resolvedQueryContainers.add(&element);
+        return QueryContainerAction::Continue;
+    }
+
+    if (m_update->isEmpty()) {
+        m_resolvedQueryContainers.add(&element);
+        return QueryContainerAction::Continue;
+    }
+
+    m_unresolvedQueryContainers.add(&element);
+
+    return QueryContainerAction::Layout;
 }
 
 std::unique_ptr<Update> TreeResolver::resolve()
@@ -638,6 +652,11 @@
         m_document.styleScope().resolver();
         return nullptr;
     }
+
+    // FIXME: Just need to restore the ancestor marking.
+    for (auto& queryContainer : m_unresolvedQueryContainers)
+        queryContainer->invalidateStyleForSubtreeInternal();
+
     if (!documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
         return WTFMove(m_update);
 

Modified: trunk/Source/WebCore/style/StyleTreeResolver.h (288905 => 288906)


--- trunk/Source/WebCore/style/StyleTreeResolver.h	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/style/StyleTreeResolver.h	2022-02-01 20:34:28 UTC (rev 288906)
@@ -55,12 +55,16 @@
 
     std::unique_ptr<Update> resolve();
 
+    bool hasUnresolvedQueryContainers() const { return !m_unresolvedQueryContainers.isEmpty(); }
+
 private:
     std::unique_ptr<RenderStyle> styleForStyleable(const Styleable&, const ResolutionContext&);
 
     void resolveComposedTree();
-    void updateQueryContainer(const Element&, const RenderStyle&);
 
+    enum class QueryContainerAction : uint8_t { None, Continue, Layout };
+    QueryContainerAction updateQueryContainer(Element&, const RenderStyle&);
+
     ElementUpdates resolveElement(Element&);
 
     static ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, const Styleable&, Change, const ResolutionContext&);
@@ -113,6 +117,9 @@
     Vector<Parent, 32> m_parentStack;
     bool m_didSeePendingStylesheet { false };
 
+    HashSet<RefPtr<Element>> m_unresolvedQueryContainers;
+    HashSet<RefPtr<Element>> m_resolvedQueryContainers;
+
     std::unique_ptr<Update> m_update;
 };
 

Modified: trunk/Source/WebCore/style/StyleUpdate.h (288905 => 288906)


--- trunk/Source/WebCore/style/StyleUpdate.h	2022-02-01 20:32:31 UTC (rev 288905)
+++ trunk/Source/WebCore/style/StyleUpdate.h	2022-02-01 20:34:28 UTC (rev 288906)
@@ -80,6 +80,7 @@
 
     const Document& document() const { return m_document; }
 
+    bool isEmpty() const { return !size(); }
     unsigned size() const { return m_elements.size() + m_texts.size(); }
 
     void addElement(Element&, Element* parent, ElementUpdates&&);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to