Fieldset NG: Support position:sticky content

LayoutBoxModelObject::UpdateStickyPositionConstraints() should allow an
anonymous fieldset content box as a sticky container.

Bug: 1128479, 1146925, 1149320
Change-Id: I12e37e347fcb4300891f524f0a2b7256d0d23d78
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2562000
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#831727}
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 53c5ca1..ed4f80eb 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -44,7 +44,6 @@
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
 #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
@@ -699,20 +698,6 @@
     AdjustStyleForDisplay(style, layout_parent_style, element,
                           element ? &element->GetDocument() : nullptr);
 
-    // TOOD(crbug.com/1146925): Sticky content in a scrollable FIELDSET triggers
-    // a DHCECK failure in |StickyPositionScrollingConstraints::
-    // AncestorContainingBlockOffset()|. We disable it until the root cause is
-    // fixed.
-    if (style.GetPosition() == EPosition::kSticky && element) {
-      for (const Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) {
-        if (const auto* fieldset = DynamicTo<HTMLFieldSetElement>(ancestor)) {
-          if (!fieldset->ComputedStyleRef().IsOverflowVisibleAlongBothAxes())
-            style.SetPosition(EPosition::kStatic);
-          break;
-        }
-      }
-    }
-
     // If this is a child of a LayoutNGCustom, we need the name of the parent
     // layout function for invalidation purposes.
     if (layout_parent_style.IsDisplayLayoutCustomBox()) {
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index eec78a97..3517624c 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -963,8 +963,11 @@
   // The location container for boxes is not always the containing block.
   LayoutObject* location_container =
       IsLayoutInline() ? Container() : To<LayoutBox>(this)->LocationContainer();
-  // Skip anonymous containing blocks.
+  // Skip anonymous containing blocks except for anonymous fieldset content box.
   while (sticky_container->IsAnonymous()) {
+    if (sticky_container->Parent() &&
+        sticky_container->Parent()->IsLayoutNGFieldset())
+      break;
     sticky_container = sticky_container->ContainingBlock();
   }
 
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content-ref.html
new file mode 100644
index 0000000..95e3c05
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<body>
+<style>
+body {
+  margin: 0;
+}
+
+.fieldset div {
+  height:1000px;
+}
+
+span {
+  background: lime;
+  display: block;
+  height: 40px;
+  position: absolute;
+  top: 4px;
+  left: 0px;
+  width: 40px;
+}
+
+.fieldset {
+  border: none;
+  height: 400px;
+  margin: 0;
+  overflow: scroll;
+  padding: 0;
+}
+</style>
+<div class="fieldset"><div><span></span></div></div>
+<script>
+document.querySelector('.fieldset').scrollTop = 1000;
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content.html
new file mode 100644
index 0000000..f60d9ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/sticky-content.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="help" href="http://crbug.com/1146925">
+<link rel="match" href="sticky-content-ref.html">
+<body>
+<style>
+body {
+  margin: 0;
+}
+
+fieldset div {
+  height:1000px;
+}
+
+span {
+  background: lime;
+  display: block;
+  height: 40px;
+  position: sticky;
+  top: 4px;
+  width: 40px;
+}
+
+fieldset {
+  border: none;
+  height: 400px;
+  margin: 0;
+  overflow: scroll;
+  padding: 0;
+}
+</style>
+<fieldset><div><span></span></div></fieldset>
+<script>
+document.querySelector('fieldset').scrollTop = 1000;
+</script>
+</body>