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&&);