Bug 1538537 - When suppressing anchoring on an scrollframe, forward to the frame that actually maintains the anchor as needed. r=dholbert, a=RyanVM DEVEDITION_77_0b9_BUILD1 DEVEDITION_77_0b9_RELEASE FIREFOX_77_0b9_BUILD1 FIREFOX_77_0b9_RELEASE
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 19 May 2020 23:57:23 +0000
changeset 591554 b56c5586464ad74e5c980e38fba121705ffcc65c
parent 591553 300dc3a419af8f977f5bcd875a88dacbd7d21120
child 591555 29433cbae4c8c162da8015607d7a317565201ac1
push id13174
push userryanvm@gmail.com
push dateThu, 21 May 2020 22:45:44 +0000
treeherdermozilla-beta@b56c5586464a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, RyanVM
bugs1538537
milestone77.0
Bug 1538537 - When suppressing anchoring on an scrollframe, forward to the frame that actually maintains the anchor as needed. r=dholbert, a=RyanVM The test-case is position-change-heuristic.html but with body and #space having overflow: hidden, which makes it fail on Nightly. Differential Revision: https://phabricator.services.mozilla.com/D75825
layout/generic/ScrollAnchorContainer.cpp
testing/web-platform/tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box.html
--- a/layout/generic/ScrollAnchorContainer.cpp
+++ b/layout/generic/ScrollAnchorContainer.cpp
@@ -361,24 +361,39 @@ void ScrollAnchorContainer::AdjustmentMa
       nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Layout"),
       Frame()->PresContext()->Document(), nsContentUtils::eLAYOUT_PROPERTIES,
       "ScrollAnchoringDisabledInContainer", arguments);
 }
 
 void ScrollAnchorContainer::SuppressAdjustments() {
   ANCHOR_LOG("Received a scroll anchor suppression for %p.\n", this);
   mSuppressAnchorAdjustment = true;
+
+  // Forward to our parent if appropriate, that is, if we don't maintain an
+  // anchor, and we can't maintain one.
+  //
+  // Note that we need to check !CanMaintainAnchor(), instead of just whether
+  // our frame is in the anchor chain of our ancestor as InvalidateAnchor()
+  // does, given some suppression triggers apply even for nodes that are not in
+  // the anchor chain.
+  if (!mAnchorNode && !CanMaintainAnchor()) {
+    if (ScrollAnchorContainer* container = FindFor(Frame())) {
+      ANCHOR_LOG(" > Forwarding to parent anchor\n");
+      container->SuppressAdjustments();
+    }
+  }
 }
 
 void ScrollAnchorContainer::InvalidateAnchor(ScheduleSelection aSchedule) {
   ANCHOR_LOG("Invalidating scroll anchor %p for %p.\n", mAnchorNode, this);
 
   if (mAnchorNode) {
     SetAnchorFlags(mScrollFrame->mScrolledFrame, mAnchorNode, false);
   } else if (mScrollFrame->mScrolledFrame->IsInScrollAnchorChain()) {
+    ANCHOR_LOG(" > Forwarding to parent anchor\n");
     // We don't maintain an anchor, and our scrolled frame is in the anchor
     // chain of an ancestor. Invalidate that anchor.
     //
     // NOTE: Intentionally not forwarding aSchedule: Scheduling is always safe
     // and not doing so is just an optimization.
     FindFor(Frame())->InvalidateAnchor();
   }
   mAnchorNode = nullptr;
copy from testing/web-platform/tests/css/css-scroll-anchoring/position-change-heuristic.html
copy to testing/web-platform/tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box.html
--- a/testing/web-platform/tests/css/css-scroll-anchoring/position-change-heuristic.html
+++ b/testing/web-platform/tests/css/css-scroll-anchoring/position-change-heuristic-in-nested-scroll-box.html
@@ -1,32 +1,35 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/css-scroll-anchoring/#suppression-triggers">
 <style>
-
 #space {
   height: 4000px;
+  overflow: hidden;
 }
 #header {
   background-color: #F5B335;
   height: 50px;
   width: 100%;
 }
 #content {
   background-color: #D3D3D3;
   height: 400px;
 }
 .scroller {
   overflow: scroll;
   position: relative;
   width: 600px;
   height: 600px;
 }
-
+body {
+  overflow: hidden;
+}
 </style>
 <div id="maybeScroller">
   <div id="space">
     <div id="header"></div>
     <div id="before"></div>
     <div id="content"></div>
   </div>
 </div>