commit 11c894dcc1a23fb27edbb33f376f12d931e138a5
parent d552295c5c50937950dfd87d3b4f6279680526d0
Author: Botond Ballo <botond@mozilla.com>
Date: Tue, 25 Nov 2025 02:48:11 +0000
Bug 2000753 - Ensure the sticky spatial node is created by the time WebRender display list building enters a sticky display item. r=mstange
The patch also relaxes assumptions made in ClipManager::SwitchItem
about an item's ASR chain, and its clip's ASR chain, overlapping,
as this was also observed not to hold in the fuzzer's testcase.
Differential Revision: https://phabricator.services.mozilla.com/D273732
Diffstat:
3 files changed, 48 insertions(+), 14 deletions(-)
diff --git a/gfx/layers/wr/ClipManager.cpp b/gfx/layers/wr/ClipManager.cpp
@@ -191,6 +191,7 @@ wr::WrSpaceAndClipChain ClipManager::SwitchItem(nsDisplayListBuilder* aBuilder,
}
const ActiveScrolledRoot* asr = aItem->GetActiveScrolledRoot();
DisplayItemType type = aItem->GetType();
+ const ActiveScrolledRoot* stickyAsr = nullptr;
if (type == DisplayItemType::TYPE_STICKY_POSITION) {
// For sticky position items, the ASR is computed differently depending on
// whether the item has a fixed descendant or not. But for WebRender
@@ -199,6 +200,8 @@ wr::WrSpaceAndClipChain ClipManager::SwitchItem(nsDisplayListBuilder* aBuilder,
// the sticky item.
auto* sticky = static_cast<nsDisplayStickyPosition*>(aItem);
asr = sticky->GetContainerASR();
+ stickyAsr = ActiveScrolledRoot::GetStickyASRFromFrame(sticky->Frame());
+ MOZ_ASSERT(stickyAsr);
}
CLIP_LOG("processing item %p (%s) asr %p clip %p, inherited = %p\n", aItem,
@@ -250,20 +253,25 @@ wr::WrSpaceAndClipChain ClipManager::SwitchItem(nsDisplayListBuilder* aBuilder,
clip = clip->mParent;
}
- // There are two ASR chains here that we need to be fully defined. One is the
- // ASR chain pointed to by |asr|. The other is the
- // ASR chain pointed to by clip->mASR. We pick the leafmost
- // of these two chains because that one will include the other. Calling
- // DefineSpatialNodes with this leafmost ASR will recursively define all the
- // ASRs that we care about for this item, but will not actually push
- // anything onto the WR stack.
- const ActiveScrolledRoot* leafmostASR = asr;
- if (clip) {
- leafmostASR = ActiveScrolledRoot::PickDescendant(leafmostASR, clip->mASR);
- }
- Maybe<wr::WrSpatialId> leafmostId =
- DefineSpatialNodes(aBuilder, leafmostASR, aItem);
- (void)leafmostId;
+ // There are up to three ASR chains here that we need to be fully defined:
+ // 1. The ASR chain pointed to by |asr|
+ // 2. The ASR chain pointed to by clip->mASR
+ // 3. For a sticky item, the ASR chain pointed to by the item's sticky ASR.
+ // This one is needed so that when we create WebRender commands for the
+ // sticky item, we can give WebRender accurate information about the
+ // spatial node we're in.
+ // These chains will often be the same, or one will include the other,
+ // but we can't rely on that always being the case, so we make a
+ // DefineSpatialNodes call on all three. These calls will recursively
+ // define all the ASRs that we care about for this item, but will not
+ // actually push anything onto the WR stack.
+ (void)DefineSpatialNodes(aBuilder, asr, aItem);
+ if (clip && clip->mASR != asr) {
+ (void)DefineSpatialNodes(aBuilder, clip->mASR, aItem);
+ }
+ if (stickyAsr && stickyAsr != asr) {
+ (void)DefineSpatialNodes(aBuilder, stickyAsr, aItem);
+ }
// Define all the clips in the item's clip chain, and obtain a clip chain id
// for it.
diff --git a/layout/base/crashtests/2000753.html b/layout/base/crashtests/2000753.html
@@ -0,0 +1,25 @@
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <style>
+ #a {
+ position: sticky;
+ clip-path: polygon(93% 0%, 0.46em 0%, 9px 18446744073709551615px, 0em 35%);
+ }
+ #b {
+ position: sticky;
+ clip-path: polygon(93% 0%, 0.46em 0%, 9px 18446744073709551615px, 0em 35%);
+ }
+ #c {
+ position: sticky;
+ }
+ </style>
+ </head>
+ <body>
+ <time id="a">
+ <time id="b">
+ <img id="c" srcset="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAIAAABt+uBvAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wDGhYvCNVA1EIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAjklEQVR42u3QIQEAMAgAsHNNVspTgARY1BZh0ZWP3VcgSJAgQYIECRKEIEGCBAkSJEgQggQJEiRIkCBBCBIkSJAgQYIECUKQIEGCBAkSJAhBggQJEiRIkCAECRIkSJAgQYIEIUiQIEGCBAkShCBBggQJEiRIEIIECRIkSJAgQYIQJEiQIEGCBAlCkCBBdwaeugIthHvZ+AAAAABJRU5ErkJggg== 1x" align="right">
+ </time>
+ </time>
+ </body>
+</html>
diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list
@@ -568,4 +568,5 @@ load 1929445.html
asserts(1-3) load 1931933.html
load 1984507.html
load 2000121.html
+skip-if(debug) load 2000753.html
load 2000991.html