Add support for `content-visibility: auto

This change adds support for `content-visibilty: auto` as well as
showing and hiding content based on the relevancy of the content as
defined in the specification. Changes to relevancy are handled by
triggering updates in a set of `content-visibility: auto` frames stored
in PresShell at the appropriate time in the document lifecycle.

Some tests are now failing due to this feature exposing the failures,
but they will be fixed in later changes.

This change is a reland of an earlier version that properly updates
intrinsic sizes and triggers an update of remembered size for the
purposes of contain-intrinsic-size when content relevancy changes.

Co-authored-by: Jihye Hong <jihye@igalia.com>

Differential Revision: https://phabricator.services.mozilla.com/D159693

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1791759
gecko-commit: c1e64e8e466506d1d9a36d747df25527bd545b10
gecko-reviewers: emilio
diff --git a/css/css-contain/content-visibility/content-visibility-070.html b/css/css-contain/content-visibility/content-visibility-070.html
index 4f63069..a41b513 100644
--- a/css/css-contain/content-visibility/content-visibility-070.html
+++ b/css/css-contain/content-visibility/content-visibility-070.html
@@ -59,8 +59,8 @@
   function step2() {
     const r = container.getBoundingClientRect();
     t.step(() => {
-      assert_equals(r.y, 3000, "step3 offset");
-      assert_equals(r.height, 10, "step3 height");
+      assert_equals(r.y, 3000, "step2 offset");
+      assert_equals(r.height, 10, "step2 height");
     });
     document.scrollingElement.scrollTop = 3000;
     requestAnimationFrame(step3);
@@ -69,8 +69,8 @@
   function step3() {
     const r = container.getBoundingClientRect();
     t.step(() => {
-      assert_less_than(r.y, 3000, "step2 offset");
-      assert_equals(r.height, 10, "step2 height");
+      assert_less_than(r.y, 3000, "step3 offset");
+      assert_equals(r.height, 10, "step3 height");
     });
     document.scrollingElement.scrollTop = 0;
     requestAnimationFrame(step4);
@@ -88,8 +88,8 @@
   function step5() {
     const r = container.getBoundingClientRect();
     t.step(() => {
-      assert_equals(r.y, 3000, "step4 offset");
-      assert_equals(r.height, 10, "step4 height");
+      assert_equals(r.y, 3000, "step5 offset");
+      assert_equals(r.height, 10, "step5 height");
     });
 
     selection.removeAllRanges();
diff --git a/css/css-contain/content-visibility/content-visibility-auto-in-iframe-ref.html b/css/css-contain/content-visibility/content-visibility-auto-in-iframe-ref.html
new file mode 100644
index 0000000..03a2875
--- /dev/null
+++ b/css/css-contain/content-visibility/content-visibility-auto-in-iframe-ref.html
@@ -0,0 +1,25 @@
+<!doctype HTML>
+<html>
+<meta charset="utf8">
+<title>CSS Content Visibility: auto container in an iframe (reference)</title>
+<link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
+
+<iframe id="frame" srcdoc='
+  <style>
+  #container {
+    width: 200px;
+    height: 200px;
+  }
+  #child {
+    width: 100px;
+    height: 100px;
+    background: green;
+  }
+  </style>
+  <div id="container">
+    <div id="child"></div>
+  </div>
+  hello
+'></iframe>
+</html>
diff --git a/css/css-contain/content-visibility/content-visibility-auto-in-iframe.html b/css/css-contain/content-visibility/content-visibility-auto-in-iframe.html
new file mode 100644
index 0000000..ba02cac
--- /dev/null
+++ b/css/css-contain/content-visibility/content-visibility-auto-in-iframe.html
@@ -0,0 +1,28 @@
+<!doctype HTML>
+<html>
+<meta charset="utf8">
+<title>CSS Content Visibility: auto container in an iframe</title>
+<link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
+<link rel="match" href="content-visibility-auto-in-iframe-ref.html">
+<meta name="assert" content="content-visibility: auto shows on screen iframe contents">
+
+<iframe id="frame" srcdoc='
+  <style>
+  #container {
+    width: 200px;
+    height: 200px;
+    content-visibility: auto;
+  }
+  #child {
+    width: 100px;
+    height: 100px;
+    background: green;
+  }
+  </style>
+  <div id="container">
+    <div id="child"></div>
+  </div>
+  hello
+'></iframe>
+</html>
diff --git a/css/css-contain/content-visibility/content-visibility-auto-intrinsic-width.html b/css/css-contain/content-visibility/content-visibility-auto-intrinsic-width.html
new file mode 100644
index 0000000..bd90fff
--- /dev/null
+++ b/css/css-contain/content-visibility/content-visibility-auto-intrinsic-width.html
@@ -0,0 +1,25 @@
+<!doctype HTML>
+<html>
+<meta charset="utf8">
+<title>Content Visibility: Elements with content-visibility: auto and intrinsic width should render correctly</title>
+<link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
+<link rel="match" href="container-ref.html">
+<meta name="assert" content="Elements with content-visibility: auto and intrinsic width should render correctly">
+
+<style>
+#container {
+  content-visibility: auto;
+  width: max-content;
+  background: lightblue;
+}
+
+#child {
+  width: 150px;
+  height: 150px;
+}
+</style>
+
+<div id="container">
+    <div id="child"></div>
+</div>
diff --git a/css/css-contain/content-visibility/content-visibility-with-top-layer-005.html b/css/css-contain/content-visibility/content-visibility-with-top-layer-005.html
new file mode 100644
index 0000000..5283aea
--- /dev/null
+++ b/css/css-contain/content-visibility/content-visibility-with-top-layer-005.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf8">
+<title>CSS Content Visibility: dialog shows under c-v auto</title>
+<link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
+<link rel="match" href="spacer-with-top-layer-ref.html">
+<meta name="assert" content="top layer dialogs render under c-v auto">
+
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+.box { width: 100px; height: 100px; border: 1px solid black; }
+.auto { content-visibility: auto }
+.spacer { width: 10px; height: 3000px; background: lightblue; }
+</style>
+
+<div class=spacer></div>
+<div id=container class="box">
+content
+<dialog id=dialog><div id=inner class="auto">PASS</div></dialog>
+</div>
+
+<script>
+function runTest() {
+  dialog.showModal();
+  takeScreenshot();
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>