summaryrefslogtreecommitdiffstats
path: root/layout/reftests/async-scrolling
diff options
context:
space:
mode:
Diffstat (limited to 'layout/reftests/async-scrolling')
-rw-r--r--layout/reftests/async-scrolling/async-scroll-and-zoom-ref.html24
-rw-r--r--layout/reftests/async-scrolling/async-scroll-and-zoom.html39
-rw-r--r--layout/reftests/async-scrolling/background-blend-mode-1-ref.html17
-rw-r--r--layout/reftests/async-scrolling/background-blend-mode-1.html26
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-1-ref.html7
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-1.html14
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-clip-1.html17
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-clip-2.html21
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-clip-ref.html11
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-mask-ref.html11
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-mask.html18
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-no-culling-1-ref.html11
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-no-culling-1.html15
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-no-culling-2-ref.html7
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-no-culling-2.html13
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-no-culling-3-ref.html7
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-no-culling-3.html15
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child-ref.html10
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-child.html16
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-cover-1-ref.html9
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-cover-1.html16
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-cover-2-ref.html10
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-cover-2.html15
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-cover-3-ref.html12
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-cover-3.html17
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-in-css-filter-ref.html29
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-in-css-filter.html34
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-in-opacity-ref.html24
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-in-opacity.html30
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-transformed-image-ref.html19
-rw-r--r--layout/reftests/async-scrolling/bg-fixed-transformed-image.html24
-rw-r--r--layout/reftests/async-scrolling/checkerboard-1-ref.html5
-rw-r--r--layout/reftests/async-scrolling/checkerboard-1.html12
-rw-r--r--layout/reftests/async-scrolling/checkerboard-2-ref.html7
-rw-r--r--layout/reftests/async-scrolling/checkerboard-2.html17
-rw-r--r--layout/reftests/async-scrolling/checkerboard-3-ref.html6
-rw-r--r--layout/reftests/async-scrolling/checkerboard-3.html15
-rw-r--r--layout/reftests/async-scrolling/contain-paint-scrollable-frame-1-ref.html8
-rw-r--r--layout/reftests/async-scrolling/contain-paint-scrollable-frame-1.html27
-rw-r--r--layout/reftests/async-scrolling/culling-1-ref.html23
-rw-r--r--layout/reftests/async-scrolling/culling-1.html20
-rw-r--r--layout/reftests/async-scrolling/curtain-effect-1-ref.html48
-rw-r--r--layout/reftests/async-scrolling/curtain-effect-1.html48
-rw-r--r--layout/reftests/async-scrolling/disable-apz-for-sle-pages-ref.html9
-rw-r--r--layout/reftests/async-scrolling/disable-apz-for-sle-pages.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1-ref.html25
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1.html36
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1-ref.html25
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1.html36
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref-b.html39
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref.html39
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-1a.html42
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-1b.html43
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-1c.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref-b.html37
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref.html37
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-2a.html42
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-2b.html43
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-2c.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-3-ref.html35
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-3a.html42
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-3b.html43
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-3c.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-4-ref.html35
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-4a.html42
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-4b.html43
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-4c.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref-t.html37
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref.html37
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-5a.html42
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-5b.html43
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-5c.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref-t.html39
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref.html39
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-6a.html42
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-6b.html43
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-6c.html46
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1-ref.html29
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1.html41
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1-ref.html29
-rw-r--r--layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1.html40
-rw-r--r--layout/reftests/async-scrolling/element-1-ref.html8
-rw-r--r--layout/reftests/async-scrolling/element-1.html12
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrollable-1-ref.html8
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrollable-1.html16
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1-ref.html30
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1.html40
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2-ref.html46
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2.html59
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3-ref.html49
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3.html65
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4-ref.html49
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4.html29
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5-ref.html13
-rw-r--r--layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5.html23
-rw-r--r--layout/reftests/async-scrolling/group-opacity-surface-size-1-ref.html36
-rw-r--r--layout/reftests/async-scrolling/group-opacity-surface-size-1.html43
-rw-r--r--layout/reftests/async-scrolling/iframe-1-ref.html10
-rw-r--r--layout/reftests/async-scrolling/iframe-1.html12
-rw-r--r--layout/reftests/async-scrolling/nested-1-ref.html10
-rw-r--r--layout/reftests/async-scrolling/nested-1.html18
-rw-r--r--layout/reftests/async-scrolling/nested-2-ref.html10
-rw-r--r--layout/reftests/async-scrolling/nested-2.html17
-rw-r--r--layout/reftests/async-scrolling/no-overscroll-ref.html24
-rw-r--r--layout/reftests/async-scrolling/offscreen-clipped-blendmode-1.html39
-rw-r--r--layout/reftests/async-scrolling/offscreen-clipped-blendmode-2.html43
-rw-r--r--layout/reftests/async-scrolling/offscreen-clipped-blendmode-3.html40
-rw-r--r--layout/reftests/async-scrolling/offscreen-clipped-blendmode-4.html44
-rw-r--r--layout/reftests/async-scrolling/offscreen-clipped-blendmode-ref.html31
-rw-r--r--layout/reftests/async-scrolling/offscreen-prerendered-active-opacity-ref.html42
-rw-r--r--layout/reftests/async-scrolling/offscreen-prerendered-active-opacity.html40
-rw-r--r--layout/reftests/async-scrolling/opaque-fractional-displayport-1.html51
-rw-r--r--layout/reftests/async-scrolling/opaque-fractional-displayport-2.html56
-rw-r--r--layout/reftests/async-scrolling/overscroll-disabled.html39
-rw-r--r--layout/reftests/async-scrolling/overscroll-fixed-iframe-overscroll.html46
-rw-r--r--layout/reftests/async-scrolling/overscroll-fixed-iframe.html53
-rw-r--r--layout/reftests/async-scrolling/overscroll-fixed-transform.html49
-rw-r--r--layout/reftests/async-scrolling/overscroll-fixed.html33
-rw-r--r--layout/reftests/async-scrolling/overscroll-ref.html24
-rw-r--r--layout/reftests/async-scrolling/overscroll-scrollbar-ref.html24
-rw-r--r--layout/reftests/async-scrolling/overscroll-scrollbar.html36
-rw-r--r--layout/reftests/async-scrolling/overscroll-subframe.html47
-rw-r--r--layout/reftests/async-scrolling/overscroll.html39
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-1-ref.html34
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-1.html33
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-2-ref.html34
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-2.html41
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-3-ref.html40
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-3.html41
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-4-ref.html44
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-4.html49
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-5-ref.html13
-rw-r--r--layout/reftests/async-scrolling/perspective-scrolling-5.html60
-rw-r--r--layout/reftests/async-scrolling/position-fixed-1-ref.html6
-rw-r--r--layout/reftests/async-scrolling/position-fixed-1.html11
-rw-r--r--layout/reftests/async-scrolling/position-fixed-2-ref.html9
-rw-r--r--layout/reftests/async-scrolling/position-fixed-2.html15
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-1-ref.html25
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-1.html34
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-2-ref.html25
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-2.html35
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-3-ref.html26
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-3.html28
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-4-ref.html46
-rw-r--r--layout/reftests/async-scrolling/position-fixed-async-zoom-4.html48
-rw-r--r--layout/reftests/async-scrolling/position-fixed-body-ref.html28
-rw-r--r--layout/reftests/async-scrolling/position-fixed-body.html32
-rw-r--r--layout/reftests/async-scrolling/position-fixed-cover-1-ref.html7
-rw-r--r--layout/reftests/async-scrolling/position-fixed-cover-1.html13
-rw-r--r--layout/reftests/async-scrolling/position-fixed-cover-2-ref.html7
-rw-r--r--layout/reftests/async-scrolling/position-fixed-cover-2.html13
-rw-r--r--layout/reftests/async-scrolling/position-fixed-cover-3-ref.html7
-rw-r--r--layout/reftests/async-scrolling/position-fixed-cover-3.html15
-rw-r--r--layout/reftests/async-scrolling/position-fixed-iframe-1-ref.html6
-rw-r--r--layout/reftests/async-scrolling/position-fixed-iframe-1.html22
-rw-r--r--layout/reftests/async-scrolling/position-fixed-iframe-2-ref.html6
-rw-r--r--layout/reftests/async-scrolling/position-fixed-iframe-2.html22
-rw-r--r--layout/reftests/async-scrolling/position-fixed-in-scroll-container-ref.html40
-rw-r--r--layout/reftests/async-scrolling/position-fixed-in-scroll-container.html50
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-clip-path-ref.html29
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-clip-path.html34
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-sticky-1-ref.html20
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-sticky-1.html33
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-sticky-2-ref.html20
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-sticky-2.html34
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-sticky-3-ref.html18
-rw-r--r--layout/reftests/async-scrolling/position-fixed-inside-sticky-3.html33
-rw-r--r--layout/reftests/async-scrolling/position-fixed-transformed-1-ref.html21
-rw-r--r--layout/reftests/async-scrolling/position-fixed-transformed-1.html23
-rw-r--r--layout/reftests/async-scrolling/position-sticky-async-zoom-1-ref.html25
-rw-r--r--layout/reftests/async-scrolling/position-sticky-async-zoom-1.html30
-rw-r--r--layout/reftests/async-scrolling/position-sticky-async-zoom-2-ref.html25
-rw-r--r--layout/reftests/async-scrolling/position-sticky-async-zoom-2.html31
-rw-r--r--layout/reftests/async-scrolling/position-sticky-bug1434250-ref.html28
-rw-r--r--layout/reftests/async-scrolling/position-sticky-bug1434250.html30
-rw-r--r--layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1-ref.html30
-rw-r--r--layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1.html36
-rw-r--r--layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-1.html15
-rw-r--r--layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-2.html15
-rw-r--r--layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-ref.html12
-rw-r--r--layout/reftests/async-scrolling/position-sticky-scrolled-clip-1-ref.html32
-rw-r--r--layout/reftests/async-scrolling/position-sticky-scrolled-clip-1.html38
-rw-r--r--layout/reftests/async-scrolling/position-sticky-scrolled-clip-2-ref.html31
-rw-r--r--layout/reftests/async-scrolling/position-sticky-scrolled-clip-2.html38
-rw-r--r--layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1-ref.html11
-rw-r--r--layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1.html14
-rw-r--r--layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2-ref.html12
-rw-r--r--layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2.html14
-rw-r--r--layout/reftests/async-scrolling/position-sticky-transformed-ref.html6
-rw-r--r--layout/reftests/async-scrolling/position-sticky-transformed.html10
-rw-r--r--layout/reftests/async-scrolling/reftest.list190
-rw-r--r--layout/reftests/async-scrolling/repeatable-diagonal-gradient.pngbin0 -> 14520 bytes
-rw-r--r--layout/reftests/async-scrolling/split-layers-1-ref.html13
-rw-r--r--layout/reftests/async-scrolling/split-layers-1.html16
-rw-r--r--layout/reftests/async-scrolling/split-layers-multi-scrolling-1-ref.html14
-rw-r--r--layout/reftests/async-scrolling/split-layers-multi-scrolling-1.html20
-rw-r--r--layout/reftests/async-scrolling/split-opacity-layers-1-ref.html12
-rw-r--r--layout/reftests/async-scrolling/split-opacity-layers-1.html15
-rw-r--r--layout/reftests/async-scrolling/sticky-inside-fixed-1-ref.html39
-rw-r--r--layout/reftests/async-scrolling/sticky-inside-fixed-1.html42
-rw-r--r--layout/reftests/async-scrolling/sticky-inside-transform-1-ref.html34
-rw-r--r--layout/reftests/async-scrolling/sticky-inside-transform-1.html35
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-1-ref.html8
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-1.html15
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-2-ref.html18
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-2.html23
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-3-ref.html19
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-3.html33
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-4-ref.html7
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-4.html14
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-5-ref.html7
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-5.html16
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-6-ref.html7
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-6.html13
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-7-ref.html28
-rw-r--r--layout/reftests/async-scrolling/sticky-pos-scrollable-7.html42
-rw-r--r--layout/reftests/async-scrolling/transformed-1-ref.html7
-rw-r--r--layout/reftests/async-scrolling/transformed-1.html10
218 files changed, 6063 insertions, 0 deletions
diff --git a/layout/reftests/async-scrolling/async-scroll-and-zoom-ref.html b/layout/reftests/async-scrolling/async-scroll-and-zoom-ref.html
new file mode 100644
index 0000000000..ecc40d5090
--- /dev/null
+++ b/layout/reftests/async-scrolling/async-scroll-and-zoom-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: -100px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/async-scroll-and-zoom.html b/layout/reftests/async-scrolling/async-scroll-and-zoom.html
new file mode 100644
index 0000000000..a7795a54d6
--- /dev/null
+++ b/layout/reftests/async-scrolling/async-scroll-and-zoom.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="550"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 500px;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that both layout and visual viewport scroll offsets are correctly applied.
+
+ An async scroll of 550 CSS pixels at 2.0x async zoom will ensure that
+ the visual viewport is scrolled beyond the bottom of the previous
+ layout viewport, meaning that the layout viewport is also scrolled so
+ that it contains the visual viewport.
+
+ Content should be scrolled by both the layout and visual offsets, in the
+ correct co-ordinate space for each, which should result the top half of
+ the div being scrolled out of view. -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/background-blend-mode-1-ref.html b/layout/reftests/async-scrolling/background-blend-mode-1-ref.html
new file mode 100644
index 0000000000..b5a9e0c12d
--- /dev/null
+++ b/layout/reftests/async-scrolling/background-blend-mode-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference: Bug 1248913 - Keep background-attachment:fixed image fixed under APZ scrolling even when a background-blend-mode is applied.</title>
+
+<style>
+
+html {
+ background: radial-gradient(circle 200px at 400px 400px, lime 100px, transparent 0) scroll,
+ radial-gradient(circle 200px at 400px 300px, blue 100px, transparent 0) scroll
+ white no-repeat;
+ background-blend-mode: multiply;
+ height: 100%;
+}
+
+</style>
+
+<div></div>
diff --git a/layout/reftests/async-scrolling/background-blend-mode-1.html b/layout/reftests/async-scrolling/background-blend-mode-1.html
new file mode 100644
index 0000000000..33a8498cec
--- /dev/null
+++ b/layout/reftests/async-scrolling/background-blend-mode-1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+
+<meta charset="utf-8">
+<title>Bug 1248913 - Keep background-attachment:fixed image fixed under APZ scrolling even when a background-blend-mode is applied.</title>
+
+<style>
+
+html {
+ background: radial-gradient(circle 200px at 400px 400px, lime 100px, transparent 0) fixed,
+ radial-gradient(circle 200px at 400px 400px, blue 100px, transparent 0) scroll
+ white no-repeat;
+ background-blend-mode: multiply;
+ scrollbar-width: none;
+}
+
+body {
+ height: 4000px;
+}
+
+</style>
+
+<div></div>
diff --git a/layout/reftests/async-scrolling/bg-fixed-1-ref.html b/layout/reftests/async-scrolling/bg-fixed-1-ref.html
new file mode 100644
index 0000000000..f8f0aef054
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-1-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="background-image:url(repeatable-diagonal-gradient.png);
+ background-repeat:no-repeat;
+ background-position:top left;">
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-1.html b/layout/reftests/async-scrolling/bg-fixed-1.html
new file mode 100644
index 0000000000..15a00dc272
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;">
+ <!-- test that background-attachment:fixed backgrounds don't move with async scrolling -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-clip-1.html b/layout/reftests/async-scrolling/bg-fixed-child-clip-1.html
new file mode 100644
index 0000000000..9d9795de71
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-clip-1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <div style="margin-top: 100px; height: 100px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;">
+ </div>
+ <!-- test that the clip of a background-attachment:fixed background of a
+ child element moves correctly during async scrolling -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-clip-2.html b/layout/reftests/async-scrolling/bg-fixed-child-clip-2.html
new file mode 100644
index 0000000000..ce0ab6cc9c
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-clip-2.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <div style="margin-top: 100px; height: 100px;
+ position: relative;">
+ <div style="position: absolute;
+ top: 0; right: 0; bottom: 0; left: 0;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;">
+ </div>
+ </div>
+ <!-- test that the clip of a background-attachment:fixed background of a
+ child element moves correctly during async scrolling -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-clip-ref.html b/layout/reftests/async-scrolling/bg-fixed-child-clip-ref.html
new file mode 100644
index 0000000000..7ae3847742
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-clip-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; margin:0;">
+ <div style="margin-top: 50px; height: 100px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;">
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-mask-ref.html b/layout/reftests/async-scrolling/bg-fixed-child-mask-ref.html
new file mode 100644
index 0000000000..c71b15b434
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-mask-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; margin:0;">
+ <div style="margin-top: 50px; height: 100px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-repeat:no-repeat;
+ background-position:0px -50px;
+ border-radius:50px;">
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-mask.html b/layout/reftests/async-scrolling/bg-fixed-child-mask.html
new file mode 100644
index 0000000000..a6fab8218e
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-mask.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <div style="margin-top: 100px; height: 100px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;
+ border-radius:50px;">
+ </div>
+ <!-- test that the clip of a background-attachment:fixed background of a
+ child element moves correctly during async scrolling -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-no-culling-1-ref.html b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-1-ref.html
new file mode 100644
index 0000000000..8f647b7c9e
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-1-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; margin:0;">
+ <div style="height: 100px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;">
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-no-culling-1.html b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-1.html
new file mode 100644
index 0000000000..123334cbdd
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <div style="height: 50px; position: relative;
+ background:url(repeatable-diagonal-gradient.png) top left fixed no-repeat;">
+ </div>
+ <div style="height: 100px;
+ background:url(repeatable-diagonal-gradient.png) top left fixed no-repeat;">
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-no-culling-2-ref.html b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-2-ref.html
new file mode 100644
index 0000000000..d5595cd827
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-2-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; margin:0;">
+ <div style="width: 200px; height: 100px; background: lime; margin-top: 200px;"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-no-culling-2.html b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-2.html
new file mode 100644
index 0000000000..be3487d4fc
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-2.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1000"
+ style="scrollbar-width:none">
+<body style="height: 3000px; margin: 0;">
+ <div style="height: 1200px;
+ background: linear-gradient(white, white) top left fixed no-repeat;">
+ </div>
+ <div style="width: 200px; height: 100px; background: lime;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-no-culling-3-ref.html b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-3-ref.html
new file mode 100644
index 0000000000..7f864457f6
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-3-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; margin:0;">
+ <div style="width: 200px; height: 100px; background: lime;"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-no-culling-3.html b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-3.html
new file mode 100644
index 0000000000..fb0616ff3b
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-no-culling-3.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-150"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-150"
+ style="scrollbar-width: none; background: linear-gradient(white, white) top left fixed no-repeat;">
+<body style="height: 3000px; margin: 0;">
+ <div style="width: 200px; height: 100px; background: lime;"></div>
+
+ <script>
+ document.documentElement.scrollTop = 150;
+ </script>
+
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child-ref.html b/layout/reftests/async-scrolling/bg-fixed-child-ref.html
new file mode 100644
index 0000000000..9ca02365f1
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; margin:0;">
+ <div style="height: 1000px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-repeat:no-repeat;
+ background-position:top left;">
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-child.html b/layout/reftests/async-scrolling/bg-fixed-child.html
new file mode 100644
index 0000000000..b90179433b
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-child.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <div style="height: 1000px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:top left;">
+ </div>
+ <!-- test that background-attachment:fixed backgrounds of child elements don't move with async scrolling -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-cover-1-ref.html b/layout/reftests/async-scrolling/bg-fixed-cover-1-ref.html
new file mode 100644
index 0000000000..b5efcc7412
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-cover-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-repeat:no-repeat;
+ background-position:0 300px;">
+ <div style="position:absolute; background:black; top:0; left:0; width:500px; height:400px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-cover-1.html b/layout/reftests/async-scrolling/bg-fixed-cover-1.html
new file mode 100644
index 0000000000..b125cfd7af
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-cover-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="400"
+ style="scrollbar-width:none">
+<body style="height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed;
+ background-repeat:no-repeat;
+ background-position:0 300px;">
+ <!-- Test that background-attachment:fixed content covered by scrolling content gets rendered
+ properly -->
+ <div style="position:absolute; background:black; top:200px; left:0; width:500px; height:600px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-cover-2-ref.html b/layout/reftests/async-scrolling/bg-fixed-cover-2-ref.html
new file mode 100644
index 0000000000..8d9601f2a8
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-cover-2-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png), url(repeatable-diagonal-gradient.png);
+ background-repeat:no-repeat;
+ background-position:0 300px, 0 0;">
+ <!-- Test that scrolling content covered by background-attachment:fixed content
+ gets rendered properly -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-cover-2.html b/layout/reftests/async-scrolling/bg-fixed-cover-2.html
new file mode 100644
index 0000000000..416a7481a4
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-cover-2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="300"
+ style="scrollbar-width:none">
+<body style="height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png), url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed, scroll;
+ background-repeat:no-repeat;
+ background-position:0 300px;">
+ <!-- Test that scrolling content covered by background-attachment:fixed content
+ gets rendered properly -->
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-cover-3-ref.html b/layout/reftests/async-scrolling/bg-fixed-cover-3-ref.html
new file mode 100644
index 0000000000..eb87febce8
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-cover-3-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png), url(repeatable-diagonal-gradient.png);
+ background-repeat:no-repeat;
+ background-position:0 300px, 0 0;">
+ <!-- Test that scrolling content above background-attachment:fixed content but not
+ intersecting it doesn't get moved down to a layer below the
+ background-attachment:fixed content -->
+ <div style="position:absolute; background:black; left:0; top:300px; width:500px; height:200px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-cover-3.html b/layout/reftests/async-scrolling/bg-fixed-cover-3.html
new file mode 100644
index 0000000000..b363e5ded2
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-cover-3.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="300"
+ style="scrollbar-width:none">
+<body style="height:3000px;
+ background-image:url(repeatable-diagonal-gradient.png), url(repeatable-diagonal-gradient.png);
+ background-attachment:fixed, scroll;
+ background-repeat:no-repeat;
+ background-position:0 300px;">
+ <!-- Test that scrolling content above background-attachment:fixed content but not
+ intersecting it doesn't get moved down to a layer below the
+ background-attachment:fixed content -->
+ <div style="position:absolute; background:black; left:0; top:600px; width:500px; height:200px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-in-css-filter-ref.html b/layout/reftests/async-scrolling/bg-fixed-in-css-filter-ref.html
new file mode 100644
index 0000000000..8dee2b2412
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-in-css-filter-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Fixed background inside blur filter</title>
+ <style>
+ .scrollable {
+ width: 100px;
+ height: 100px;
+ overflow: hidden;
+ }
+ .bg {
+ width: 100px;
+ height: 100px;
+ background-image: url("repeatable-diagonal-gradient.png");
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ }
+ .blur {
+ filter: blur(10px);
+ }
+ </style>
+</head>
+<body>
+<div class="scrollable">
+ <div class="bg blur"></div>
+</div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-in-css-filter.html b/layout/reftests/async-scrolling/bg-fixed-in-css-filter.html
new file mode 100644
index 0000000000..4f02252c66
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-in-css-filter.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<head>
+ <meta charset="UTF-8">
+ <title>Fixed background inside blur filter</title>
+ <style>
+ .scrollable {
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+ scrollbar-width: none;
+ }
+ .bg {
+ width: 100px;
+ height: 100px;
+ background-image: url("repeatable-diagonal-gradient.png");
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ }
+ .blur {
+ filter: blur(10px);
+ }
+ </style>
+</head>
+<body>
+<div class="scrollable"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="100" reftest-displayport-h="200"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+ <div class="bg"></div>
+ <div class="bg blur"></div>
+</div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-in-opacity-ref.html b/layout/reftests/async-scrolling/bg-fixed-in-opacity-ref.html
new file mode 100644
index 0000000000..9d54bd8139
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-in-opacity-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html reftest-async-scroll >
+<style>
+
+body {
+ margin: 0px;
+ position: relative;
+ height: 1200.23px;
+ overflow: hidden;
+}
+
+.fixed-background {
+ position: absolute;
+ top: 0px;
+ bottom: 0px;
+ width: 100px;
+ background: linear-gradient(blue, blue) no-repeat fixed 0px 200px;
+ background-size: 100px 100px;
+ opacity: 0.5;
+}
+
+</style>
+<div style="overflow: hidden;" class="fixed-background"></div>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-in-opacity.html b/layout/reftests/async-scrolling/bg-fixed-in-opacity.html
new file mode 100644
index 0000000000..e565487c7c
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-in-opacity.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50.23">
+<style>
+
+html {
+ scrollbar-width: none;
+}
+
+body {
+ margin: 0px;
+ position: relative;
+ height: 1200.23px;
+}
+
+.fixed-background {
+ position: absolute;
+ top: 0px;
+ bottom: 0px;
+ width: 100px;
+ background: linear-gradient(blue, blue) no-repeat fixed 0px 200px;
+ background-size: 100px 100px;
+ opacity: 0.5;
+}
+
+</style>
+<div style="overflow: hidden;" class="fixed-background"></div>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-transformed-image-ref.html b/layout/reftests/async-scrolling/bg-fixed-transformed-image-ref.html
new file mode 100644
index 0000000000..a59d053c49
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-transformed-image-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+
+<style>
+
+body {
+ margin: 0;
+ overflow: hidden;
+}
+
+div {
+ height: 1400px;
+ background: url(repeatable-diagonal-gradient.png) top left / 512px 512px no-repeat
+}
+
+</style>
+
+<div></div>
+</html>
diff --git a/layout/reftests/async-scrolling/bg-fixed-transformed-image.html b/layout/reftests/async-scrolling/bg-fixed-transformed-image.html
new file mode 100644
index 0000000000..40ff239b3b
--- /dev/null
+++ b/layout/reftests/async-scrolling/bg-fixed-transformed-image.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+<style>
+
+html {
+ scrollbar-width: none;
+}
+
+body {
+ margin: 0;
+}
+
+div {
+ height: 1400px;
+ background: url(repeatable-diagonal-gradient.png) top left / 512px 512px fixed no-repeat
+}
+
+</style>
+
+<div></div>
+</html>
diff --git a/layout/reftests/async-scrolling/checkerboard-1-ref.html b/layout/reftests/async-scrolling/checkerboard-1-ref.html
new file mode 100644
index 0000000000..1c3a1e4555
--- /dev/null
+++ b/layout/reftests/async-scrolling/checkerboard-1-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML>
+<html>
+<body style="background-color: green; overflow:hidden">
+ <div style="position:absolute; left: 0px; top: 0px; width: 100px; height: 200px; background-color: red"></div>
+</body>
diff --git a/layout/reftests/async-scrolling/checkerboard-1.html b/layout/reftests/async-scrolling/checkerboard-1.html
new file mode 100644
index 0000000000..b41f745bb7
--- /dev/null
+++ b/layout/reftests/async-scrolling/checkerboard-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1800"
+ style="scrollbar-width:none">
+<!-- This is a simple test where we set the async-scroll position so that it
+ extends outside the displayport, and ensure that the checkerboarded area
+ is filled with the expected background color. -->
+<body style="background-color: green; height: 5000px">
+ <div style="position:absolute; left: 0px; top: 1800px; width: 100px; height: 400px; background-color: red"></div>
+</body>
diff --git a/layout/reftests/async-scrolling/checkerboard-2-ref.html b/layout/reftests/async-scrolling/checkerboard-2-ref.html
new file mode 100644
index 0000000000..6a12210c05
--- /dev/null
+++ b/layout/reftests/async-scrolling/checkerboard-2-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="background-color: green; overflow:hidden">
+ <div style="position:fixed; left: 0px; top: 0px; width: 100px; height: 500px; background-color: purple; z-index: -1"></div>
+ <div style="position:absolute; left: 0px; top: 0px; background-color: yellow; width: 100px; height: 200px"></div>
+ <div style="position:fixed; left: 10px; top: 10px; width: 10px; height: 10px; background-color: blue"></div>
+</body>
diff --git a/layout/reftests/async-scrolling/checkerboard-2.html b/layout/reftests/async-scrolling/checkerboard-2.html
new file mode 100644
index 0000000000..170705ba26
--- /dev/null
+++ b/layout/reftests/async-scrolling/checkerboard-2.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1800"
+ style="scrollbar-width: none">
+<!-- This is a test where we set the async-scroll position so that it
+ extends outside the displayport, but also have some fixed-position
+ elements in the mix. In particular, the purple element is below
+ (in z-order) the main scrolling content and should not be made visible
+ while checkerboarding; the checkerboarding code should cover it up
+ with the appropriate background color. -->
+<body style="background-color: green; height: 5000px">
+ <div style="position:fixed; left: 0px; top: 0px; width: 100px; height: 500px; background-color: purple; z-index: -1"></div>
+ <div style="position:absolute; left: 0px; top: 500px; background-color: yellow; width: 100px; height: 4500px"></div>
+ <div style="position:fixed; left: 10px; top: 10px; width: 10px; height: 10px; background-color: blue"></div>
+</body>
diff --git a/layout/reftests/async-scrolling/checkerboard-3-ref.html b/layout/reftests/async-scrolling/checkerboard-3-ref.html
new file mode 100644
index 0000000000..d00946ada6
--- /dev/null
+++ b/layout/reftests/async-scrolling/checkerboard-3-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body style="background-color: green; overflow:hidden">
+ <div style="position:fixed; left: 0px; top: 0px; width: 100px; height: 500px; background-color: purple; z-index: -1"></div>
+ <div style="position:fixed; left: 10px; top: 10px; width: 10px; height: 10px; background-color: blue"></div>
+</body>
diff --git a/layout/reftests/async-scrolling/checkerboard-3.html b/layout/reftests/async-scrolling/checkerboard-3.html
new file mode 100644
index 0000000000..4d3e7214a6
--- /dev/null
+++ b/layout/reftests/async-scrolling/checkerboard-3.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="2100"
+ style="scrollbar-width: none">
+<!-- This is the exact same test as checkerboard-2.html, but we put
+ the scroll position entirely outside of the displayport. This ensures
+ that even we do the proper checkerboarding even if the layer would
+ otherwise be culled out in the compositor because it is not on-screen. -->
+<body style="background-color: green; height: 5000px">
+ <div style="position:fixed; left: 0px; top: 0px; width: 100px; height: 500px; background-color: purple; z-index: -1"></div>
+ <div style="position:absolute; left: 0px; top: 500px; background-color: yellow; width: 100px; height: 4500px"></div>
+ <div style="position:fixed; left: 10px; top: 10px; width: 10px; height: 10px; background-color: blue"></div>
+</body>
diff --git a/layout/reftests/async-scrolling/contain-paint-scrollable-frame-1-ref.html b/layout/reftests/async-scrolling/contain-paint-scrollable-frame-1-ref.html
new file mode 100644
index 0000000000..e125681101
--- /dev/null
+++ b/layout/reftests/async-scrolling/contain-paint-scrollable-frame-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:200px;
+ border:2px solid black; background: lime;">
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/contain-paint-scrollable-frame-1.html b/layout/reftests/async-scrolling/contain-paint-scrollable-frame-1.html
new file mode 100644
index 0000000000..471258a265
--- /dev/null
+++ b/layout/reftests/async-scrolling/contain-paint-scrollable-frame-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <div style="width:400px; height:200px; overflow:scroll;
+ scrollbar-width: none;
+ border:2px solid black; background: red;
+ contain:paint;"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+ <!-- This element is what we're hoping will fill the scrollport
+ when the reftest snapshot is taken: -->
+ <div style="background: lime; margin-top: 100px; height: 600px"></div>
+
+ <!-- This element is just to be sure the scrollframe's "contain:paint"
+ styling is actually having an effect. "contain:paint" should make the
+ scrollframe become a containing block for this fixed-pos element, and
+ then this element will position itself off the bottom of the
+ scrollframe and will be entirely clipped. If we fail to honor
+ "contain:paint" for some reason, then this element will instead use
+ the *viewport* as its containing block, and it'll show up in the
+ reftest snapshot and cause the reftest to fail. -->
+ <div style="position: fixed; top: 320px; width: 50px; height: 50px;
+ background: purple;"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/culling-1-ref.html b/layout/reftests/async-scrolling/culling-1-ref.html
new file mode 100644
index 0000000000..5a827ddb8c
--- /dev/null
+++ b/layout/reftests/async-scrolling/culling-1-ref.html
@@ -0,0 +1,23 @@
+<html>
+ <head>
+ <title>Culling Test</title>
+ <meta name="viewport" content="width=device-width">
+ </head>
+ <body style="background:red" onload="loaded()">
+ <div style="height:390px; width:300px; overflow-y:auto; background:red; scrollbar-width:none">
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin-top:15px; width:300px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ </div>
+ <script>
+ function loaded() {
+ var scrollableDiv = document.querySelector("div");
+ scrollableDiv.scrollTop = 10;
+ }
+ </script>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/culling-1.html b/layout/reftests/async-scrolling/culling-1.html
new file mode 100644
index 0000000000..c8a62602a4
--- /dev/null
+++ b/layout/reftests/async-scrolling/culling-1.html
@@ -0,0 +1,20 @@
+<html reftest-async-scroll>
+ <head>
+ <title>Culling Test</title>
+ <meta name="viewport" content="width=device-width">
+ </head>
+ <body style="background:red">
+ <div style="height:390px; width:300px; overflow-y:auto; background:red; scrollbar-width:none"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="300" reftest-displayport-h="400"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="10">
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin-top:15px; width:300px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ <div style="margin:15px; width:200px; height:40px; background:blue"></div>
+ </div>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/curtain-effect-1-ref.html b/layout/reftests/async-scrolling/curtain-effect-1-ref.html
new file mode 100644
index 0000000000..003cd019c5
--- /dev/null
+++ b/layout/reftests/async-scrolling/curtain-effect-1-ref.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html style="margin: 0; padding: 0; z-index: 0">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<body style="margin: 0; padding: 0; z-index: 0" onload="scrollTo(0,400)">
+
+<div style="height: 100vh">
+<div style="width: 100%;
+ height: 100vh;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2">
+<div style="position: absolute;
+ width: 100%;
+ height: 100vh;
+ left: 0;
+ top: 0;
+ z-index: 3">
+<div style="position: relative;
+ width: 100%;
+ height: 100%;
+ background-image: linear-gradient(lime, blue);">
+</div></div></div></div>
+
+<div style="height: 100vh;
+ position: relative;
+ background: black;">
+<div style="position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ clip: rect(0, auto, auto, 0);">
+<div style="width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: fixed;
+ transform: translateZ(0);
+ z-index: 3">
+<div style="position: relative;
+ width: 100%;
+ height: 100%;
+ background-image: linear-gradient(yellow, red);">
+</div></div></div></div>
+</body></html>
diff --git a/layout/reftests/async-scrolling/curtain-effect-1.html b/layout/reftests/async-scrolling/curtain-effect-1.html
new file mode 100644
index 0000000000..09d57c23b1
--- /dev/null
+++ b/layout/reftests/async-scrolling/curtain-effect-1.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html style="margin: 0; padding: 0; z-index: 0" reftest-async-scroll reftest-async-scroll-y="400">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<body style="margin: 0; padding: 0; z-index: 0">
+
+<div style="height: 100vh">
+<div style="width: 100%;
+ height: 100vh;
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2">
+<div style="position: absolute;
+ width: 100%;
+ height: 100vh;
+ left: 0;
+ top: 0;
+ z-index: 3">
+<div style="position: relative;
+ width: 100%;
+ height: 100%;
+ background-image: linear-gradient(lime, blue);">
+</div></div></div></div>
+
+<div style="height: 100vh;
+ position: relative;
+ background: black;">
+<div style="position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ clip: rect(0, auto, auto, 0);">
+<div style="width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ position: fixed;
+ transform: translateZ(0);
+ z-index: 3">
+<div style="position: relative;
+ width: 100%;
+ height: 100%;
+ background-image: linear-gradient(yellow, red);">
+</div></div></div></div>
+</body></html>
diff --git a/layout/reftests/async-scrolling/disable-apz-for-sle-pages-ref.html b/layout/reftests/async-scrolling/disable-apz-for-sle-pages-ref.html
new file mode 100644
index 0000000000..9948693471
--- /dev/null
+++ b/layout/reftests/async-scrolling/disable-apz-for-sle-pages-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Check that the apz.disable_for_sle_pages pref behaves as expected</title>
+ </head>
+ <body style="height: 5000px; background-image:url(repeatable-diagonal-gradient.png);">
+ <div id="fake-fixed" style="position: absolute; top: 100px; left: 100px; width: 100px; height: 100px; background-color: green"></div>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/disable-apz-for-sle-pages.html b/layout/reftests/async-scrolling/disable-apz-for-sle-pages.html
new file mode 100644
index 0000000000..8db572f7a7
--- /dev/null
+++ b/layout/reftests/async-scrolling/disable-apz-for-sle-pages.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html class="reftest-wait reftest-snapshot-all reftest-no-flush" reftest-async-scroll
+ reftest-async-scroll-y="200">
+ <head>
+ <title>Check that the apz.disable_for_sle_pages pref behaves as expected</title>
+ <script>
+ // Upon load, this page invokes scrollTo() for a transparent element
+ // repeatedly. It triggers scroll events, which run the scroll listener
+ // below. The scroll listener updates the background-position-x of the div
+ // to make the div a scroll-linked-effect. The scroll-linked effect detector
+ // should then report that the document contains such an effect, which will
+ // disable APZ on the page. That in turn will cause the
+ // reftest-async-scroll-y to get ignored, and that's what the reftest checks
+ // for.
+
+ function start() {
+ let scrollPosition = 1;
+
+ scroller.addEventListener('scroll', function() {
+ // NOTE: Changing background-position-x doesn't change rendering for
+ // this element.
+ document.getElementById('scroll-linked-effect').style.backgroundPositionX =
+ scroller.scrollTop + "px";
+ if (scrollPosition == 1) {
+ setTimeout(done, 0);
+ }
+ scrollPosition++;
+ scroller.scrollTo(0, scrollPosition);
+ });
+
+ scroller.scrollTo(0, scrollPosition);
+ }
+ addEventListener('load', start, false);
+
+ function done() {
+ document.documentElement.classList.remove('reftest-wait');
+ }
+ </script>
+ </head>
+ <body style="height: 5000px; background-image:url(repeatable-diagonal-gradient.png);">
+ <div id="scroller" style="overflow: auto; width: 100px; height: 100px; scrollbar-width: none;">
+ <div style="height: 5000px;"></div>
+ </div>
+ <div id="scroll-linked-effect" style="position: absolute; top: 100px; left: 100px; width: 100px; height: 100px; background-color: green"></div>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1-ref.html
new file mode 100644
index 0000000000..bbac8734d5
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ height: 2000px;
+ width: 100%;
+}
+#fixed {
+ width: 100%;
+ height: 200px;
+ position: fixed;
+ bottom: 0;
+ background: red;
+ margin-bottom: 50px;
+}
+</style>
+<body>
+ <div id="scrolled"></div>
+ <div id="fixed"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1.html b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1.html
new file mode 100644
index 0000000000..4f980e271c
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-bottom-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<!--
+ Tests that setting a fixed bottom margin in the compositor results
+ in the margin being applied to an element fixed to the bottom.
+
+ The fixed margin is specified as a test-pref in reftest.list.
+
+ The purpose of the fixed margin is to compensate for the transform that the
+ dynamic toolbar applies to the entire content area. We don't have a way of
+ simulating that transform in a reftest, so the fixed margin in isolation will
+ cause the fixed element to be offset from the bottom of the screen, and in
+ the ref page we use a regular CSS "margin-bottom" to match the rendering.
+-->
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ height: 2000px;
+ width: 100%;
+}
+#fixed {
+ width: 100%;
+ height: 200px;
+ position: fixed;
+ bottom: 0;
+ background: red;
+}
+</style>
+<body>
+ <div id="scrolled"></div>
+ <div id="fixed"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1-ref.html
new file mode 100644
index 0000000000..0fe473de2a
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ height: 2000px;
+ width: 100%;
+}
+#fixed {
+ width: 100%;
+ height: 200px;
+ position: fixed;
+ top: 0;
+ background: red;
+ margin-top: 50px;
+}
+</style>
+<body>
+ <div id="scrolled"></div>
+ <div id="fixed"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1.html b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1.html
new file mode 100644
index 0000000000..6123371f5f
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-fixed-top-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<!--
+ Tests that setting a fixed top margin in the compositor results
+ in the margin being applied to an element fixed to the top.
+
+ The fixed margin is specified as a test-pref in reftest.list.
+
+ The purpose of the fixed margin is to compensate for the transform that the
+ dynamic toolbar applies to the entire content area. We don't have a way of
+ simulating that transform in a reftest, so the fixed margin in isolation will
+ cause the fixed element to be offset from the top of the screen, and in
+ the ref page we use a regular CSS "margin-top" to match the rendering.
+-->
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ height: 2000px;
+ width: 100%;
+}
+#fixed {
+ width: 100%;
+ height: 200px;
+ position: fixed;
+ top: 0;
+ background: red;
+}
+</style>
+<body>
+ <div id="scrolled"></div>
+ <div id="fixed"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref-b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref-b.html
new file mode 100644
index 0000000000..bcf56579c2
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref-b.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: relative;
+ top: calc(-50px - 20px + 10px - 50px);
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: calc(-100px - 20px + 10px - 50px);
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 10;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref.html
new file mode 100644
index 0000000000..ebb7972d3a
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1-ref.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: relative;
+ top: calc(-50px - 20px + 10px);
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: calc(-100px - 20px + 10px);
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 10;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1a.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1a.html
new file mode 100644
index 0000000000..c7147c01b1
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1a.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 10;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1b.html
new file mode 100644
index 0000000000..4cb4e16d58
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1b.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="10">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1c.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1c.html
new file mode 100644
index 0000000000..d180d26163
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-1c.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-1150"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-1140">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref-b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref-b.html
new file mode 100644
index 0000000000..eb13c69a46
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref-b.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: calc(-20px - 50px);
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 100;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref.html
new file mode 100644
index 0000000000..44318d939e
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: -20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 100;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2a.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2a.html
new file mode 100644
index 0000000000..b94890ae26
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2a.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 100;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2b.html
new file mode 100644
index 0000000000..87e6f91cf0
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2b.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2c.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2c.html
new file mode 100644
index 0000000000..889f61e059
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-2c.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-1150"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-1050">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3-ref.html
new file mode 100644
index 0000000000..98aa3dd23b
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 130;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3a.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3a.html
new file mode 100644
index 0000000000..1f024fa5ca
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3a.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 130;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3b.html
new file mode 100644
index 0000000000..78922be7eb
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3b.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="130">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3c.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3c.html
new file mode 100644
index 0000000000..30adcafc0d
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-3c.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-1150"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-1020">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4-ref.html
new file mode 100644
index 0000000000..1357b07703
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1020;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4a.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4a.html
new file mode 100644
index 0000000000..f626cfa44f
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4a.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1020;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4b.html
new file mode 100644
index 0000000000..d62fe0e5af
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4b.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1020">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4c.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4c.html
new file mode 100644
index 0000000000..0005b0471e
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-4c.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-1150"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-130">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref-t.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref-t.html
new file mode 100644
index 0000000000..489d7f9d98
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref-t.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: calc(20px + 50px);
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1050;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref.html
new file mode 100644
index 0000000000..acd01a3a93
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1050;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5a.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5a.html
new file mode 100644
index 0000000000..640c8fa43c
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5a.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1050;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5b.html
new file mode 100644
index 0000000000..9ea9d154f9
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5b.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1050">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5c.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5c.html
new file mode 100644
index 0000000000..2d7e087fe3
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-5c.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-1150"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-100">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref-t.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref-t.html
new file mode 100644
index 0000000000..3276137a99
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref-t.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: calc(100px + 20px - 10px + 50px);
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: relative;
+ top: calc(50px + 20px - 10px + 50px);
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1140;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref.html
new file mode 100644
index 0000000000..7a01152ec5
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6-ref.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: relative;
+ top: calc(100px + 20px - 10px);
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: relative;
+ top: calc(50px + 20px - 10px);
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1140;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6a.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6a.html
new file mode 100644
index 0000000000..dbe019fd34
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6a.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = 1140;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6b.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6b.html
new file mode 100644
index 0000000000..9044587caf
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6b.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1140">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6c.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6c.html
new file mode 100644
index 0000000000..292b268c0c
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-6c.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="-1150"
+ reftest-displayport-w="800" reftest-displayport-h="2150"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-10">
+<meta name="viewport" content="width=device-width">
+<style>
+html, body {
+ margin: 0;
+ scrollbar-width: none;
+}
+.spacer {
+ height: 100vh;
+ background-color: green;
+}
+.sticky_bottom {
+ position: sticky;
+ bottom: 20px;
+ height: 50px;
+ background-color: blue;
+ opacity: 50%;
+}
+.sticky_both {
+ position: sticky;
+ top: 20px;
+ bottom: 20px;
+ height: 50px;
+ background-color: purple;
+ opacity: 50%;
+}
+.sticky_top {
+ position: sticky;
+ top: 20px;
+ height: 50px;
+ background-color: red;
+ opacity: 50%;
+}
+</style>
+<div class="spacer"></div>
+<div class="sticky_bottom"></div>
+<div class="sticky_both"></div>
+<div class="sticky_top"></div>
+<div class="spacer"></div>
+<script>
+document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax;
+</script>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1-ref.html
new file mode 100644
index 0000000000..8ff4497812
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1-ref.html
@@ -0,0 +1,29 @@
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ display: flex;
+ justify-content: space-around;
+ align-items: flex-start;
+
+ height: 2000px;
+ width: 100%;
+}
+#sticky {
+ width: 100%;
+ height: 200px;
+ position: sticky;
+ bottom: 70px;
+ background: red;
+ align-self: flex-end;
+}
+</style>
+<body>
+ <div id="scrolled">
+ <div id="sticky"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1.html
new file mode 100644
index 0000000000..b401ff21db
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-bottom-1.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<!--
+ Tests that setting a fixed bottom margin in the compositor results
+ in the margin being applied to an element sticky to the bottom.
+
+ The fixed margin is specified as a test-pref in reftest.list.
+
+ The purpose of the fixed margin is to compensate for the transform that the
+ dynamic toolbar applies to the entire content area. We don't have a way of
+ simulating that transform in a reftest, so the fixed margin in isolation will
+ cause the sticky element to be offset from the bottom of the screen.
+-->
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ display: flex;
+ justify-content: space-around;
+ align-items: flex-start;
+
+ height: 2000px;
+ width: 100%;
+}
+#sticky {
+ width: 100%;
+ height: 200px;
+ position: sticky;
+ bottom: 20px;
+ background: red;
+ align-self: flex-end;
+}
+</style>
+<body>
+ <div id="scrolled">
+ <div id="sticky"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1-ref.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1-ref.html
new file mode 100644
index 0000000000..f9bc7b6ea2
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1-ref.html
@@ -0,0 +1,29 @@
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ display: flex;
+ justify-content: space-around;
+ align-items: flex-start;
+
+ height: 2000px;
+ width: 100%;
+}
+#sticky {
+ width: 100%;
+ height: 200px;
+ position: sticky;
+ top: 70px;
+ background: red;
+ align-self: flex-start;
+}
+</style>
+<body>
+ <div id="scrolled">
+ <div id="sticky"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1.html b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1.html
new file mode 100644
index 0000000000..1952a9c086
--- /dev/null
+++ b/layout/reftests/async-scrolling/dynamic-toolbar-sticky-top-1.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<!--
+ Tests that setting a fixed top margin in the compositor results
+ in the margin being applied to an element sticky to the top.
+
+ The fixed margin is specified as a test-pref in reftest.list.
+
+ The purpose of the fixed margin is to compensate for the transform that the
+ dynamic toolbar applies to the entire content area. We don't have a way of
+ simulating that transform in a reftest, so the fixed margin in isolation will
+ cause the fixed element to be offset from the top of the screen.
+-->
+<html>
+<meta name="viewport" content="width=device-width">
+<style>
+html {
+ scrollbar-width: none;
+}
+#scrolled {
+ display: flex;
+ justify-content: space-around;
+ align-items: flex-start;
+
+ height: 2000px;
+ width: 100%;
+}
+#sticky {
+ width: 100%;
+ height: 200px;
+ position: sticky;
+ top: 20px;
+ background: red;
+}
+</style>
+<body>
+ <div id="scrolled">
+ <div id="sticky"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/element-1-ref.html b/layout/reftests/async-scrolling/element-1-ref.html
new file mode 100644
index 0000000000..f7c40e2c5e
--- /dev/null
+++ b/layout/reftests/async-scrolling/element-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:500px; border:2px solid black">
+ <div style="height:450px"></div>
+ <div style="height:50px; background:purple"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/element-1.html b/layout/reftests/async-scrolling/element-1.html
new file mode 100644
index 0000000000..857c37cb7c
--- /dev/null
+++ b/layout/reftests/async-scrolling/element-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <!-- Test that element content scrolls asynchronously -->
+ <div style="width:400px; height:500px; overflow:scroll; scrollbar-width: none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="height:500px"></div>
+ <div style="height:100px; background:purple"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrollable-1-ref.html b/layout/reftests/async-scrolling/fixed-pos-scrollable-1-ref.html
new file mode 100644
index 0000000000..5996b776ed
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrollable-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<meta name="viewport" content="width=device-width">
+<body style="height: 5000px; overflow:hidden">
+ <div style="display: block; margin-top: 100px; position:fixed; overflow:scroll; top: 0px; width: 50px; height: 100px"><div style="height:200px; background-color: red"></div></div>
+ <div style="display: block; margin-top: 20px; position:relative; left: 50px; width: 50px; height: 100px; background-color: red"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrollable-1.html b/layout/reftests/async-scrolling/fixed-pos-scrollable-1.html
new file mode 100644
index 0000000000..8ab6ac6217
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrollable-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="80"
+ style="scrollbar-width: none">
+<meta name="viewport" content="width=device-width">
+<body style="height: 5000px">
+ <!-- In this test the fixed-position element is a child of the scrollable layer, but
+ gets a clip rect because it is itself a container for scrolling sublayers. This
+ tests that such a layer is transformed correctly while an async scroll transform
+ is in effect. -->
+ <div style="display: block; margin-top: 100px; position:fixed; overflow:scroll; top: 0px; width: 50px; height: 100px"><div style="height:200px; background-color: red"></div></div>
+ <div style="display: block; margin-top: 100px; position:relative; left: 50px; width: 50px; height: 100px; background-color: red"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1-ref.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1-ref.html
new file mode 100644
index 0000000000..cf4e8ac543
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+
+<title>Reference for: position:fixed with scrolled clip should prerender everything and correctly move the clip</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.greenSquare {
+ position: absolute;
+ top: 300px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: lime;
+}
+
+</style>
+
+<div class="greenSquare"></div>
+
+<script>
+
+document.documentElement.scrollTop = 200;
+
+</script>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1.html
new file mode 100644
index 0000000000..1313239431
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-1.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="200">
+
+<title>position:fixed with scrolled clip should prerender everything and correctly move the clip</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.absoluteClip {
+ position: absolute;
+ top: 300px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: red;
+ clip: rect(auto auto auto auto);
+}
+
+.fixed {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: linear-gradient(lime, lime) black 0 100px no-repeat;
+ background-size: 100% 200px;
+}
+
+</style>
+
+<div class="absoluteClip">
+ <div class="fixed"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2-ref.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2-ref.html
new file mode 100644
index 0000000000..e669c97d44
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+
+<title>Reference for: position:fixed should not be clipped by the subframe clip, but it should be clipped by the "clip" clip, and the "clip" clip should be moved by the subframe.</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.subframe {
+ margin-top: 300px;
+ width: 400px;
+ height: 400px;
+ overflow: auto;
+}
+
+.subframeScrolled {
+ height: 800px;
+}
+
+.greenSquare {
+ position: absolute;
+ top: 150px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: lime;
+}
+
+</style>
+
+<div class="subframe">
+ <div class="subframeScrolled"></div>
+</div>
+
+<div class="greenSquare"></div>
+
+<script>
+
+document.documentElement.scrollTop = 50;
+document.querySelector('.subframe').scrollTop = 150;
+
+</script>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2.html
new file mode 100644
index 0000000000..a2477b520d
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-2.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+
+<title>position:fixed should not be clipped by the subframe clip, but it should be clipped by the "clip" clip, and the "clip" clip should be moved by the subframe.</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.subframe {
+ margin-top: 300px;
+ width: 400px;
+ height: 400px;
+ overflow: auto;
+}
+
+.subframeScrolled {
+ height: 800px;
+ position: relative;
+}
+
+.absoluteClip {
+ position: absolute;
+ top: 0px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: red;
+ clip: rect(auto auto auto auto);
+}
+
+.fixed {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: linear-gradient(lime, lime) black 0 100px no-repeat;
+ background-size: 100% 200px;
+}
+
+</style>
+
+<div class="subframe"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="400" reftest-displayport-h="800"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="150">
+ <div class="subframeScrolled">
+ <div class="absoluteClip">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3-ref.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3-ref.html
new file mode 100644
index 0000000000..778ea52a76
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+
+<title>Reference for: like fixed-pos-scrolled-clip-1.html, but inside a transform. This also tests that scrolling the root scroll frame moves the "fixed" layer which is only fixed with respect to the transform, not with respect to the viewport.</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.subframe {
+ position: relative;
+ left: 10px;
+ top: 10px;
+ width: 500px;
+ height: 600px;
+ overflow: auto;
+ box-shadow: 0 0 0 2px black;
+}
+
+.scrolled {
+ height: 4000px;
+}
+
+.greenSquare {
+ position: absolute;
+ top: 300px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: lime;
+}
+
+</style>
+
+<div class="subframe">
+ <div class="scrolled">
+ <div class="greenSquare"></div>
+ </div>
+</div>
+
+<script>
+
+document.documentElement.scrollTop = 20;
+document.querySelector('.subframe').scrollTop = 200;
+
+</script>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3.html
new file mode 100644
index 0000000000..83d82cb8fc
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-3.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="20">
+
+<title>like fixed-pos-scrolled-clip-1.html, but inside a transform. This also tests that scrolling the root scroll frame moves the "fixed" layer which is only fixed with respect to the transform, not with respect to the viewport.</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.transform {
+ transform: translate(10px, 10px);
+ width: 500px;
+}
+
+.subframe {
+ height: 600px;
+ overflow: auto;
+ box-shadow: 0 0 0 2px black;
+}
+
+.scrolled {
+ height: 4000px;
+ position: relative;
+}
+
+.absoluteClip {
+ position: absolute;
+ top: 300px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: red;
+ clip: rect(auto auto auto auto);
+}
+
+.fixed {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: linear-gradient(lime, lime) black 0 100px no-repeat;
+ background-size: 100% 200px;
+}
+
+</style>
+
+<div class="transform">
+ <div class="subframe"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="200">
+ <div class="scrolled">
+ <div class="absoluteClip">
+ <div class="fixed"></div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4-ref.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4-ref.html
new file mode 100644
index 0000000000..a338c1545e
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+
+<title>Reference for: This is fixed-pos-scrolled-clip-1.html in an iframe</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.subframe {
+ position: relative;
+ left: 10px;
+ top: 10px;
+ width: 500px;
+ height: 600px;
+ overflow: auto;
+ box-shadow: 0 0 0 2px black;
+}
+
+.scrolled {
+ height: 4000px;
+}
+
+.greenSquare {
+ position: absolute;
+ top: 300px;
+ left: 100px;
+ width: 200px;
+ height: 200px;
+ background: lime;
+}
+
+</style>
+
+<div class="subframe">
+ <div class="scrolled">
+ <div class="greenSquare"></div>
+ </div>
+</div>
+
+<script>
+
+document.documentElement.scrollTop = 20;
+document.querySelector('.subframe').scrollTop = 200;
+
+</script>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4.html
new file mode 100644
index 0000000000..6c141530ef
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-4.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="20">
+
+<title>This is fixed-pos-scrolled-clip-1.html in an iframe</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.subframe {
+ position: relative;
+ left: 10px;
+ top: 10px;
+ border: 0;
+ width: 500px;
+ height: 600px;
+ overflow: auto;
+ box-shadow: 0 0 0 2px black;
+}
+
+</style>
+
+<iframe class="subframe" src="fixed-pos-scrolled-clip-1.html"></iframe>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5-ref.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5-ref.html
new file mode 100644
index 0000000000..5cf6a9375d
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en-US"><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>The scrolled clip on the fixed element is not respected</title>
+
+</head><body><div style="
+ position: absolute;
+ top: 0;
+ left: 0;
+ background-color: lime;
+ width: 100%;
+ height: 200px;">
+</div>
+</body></html>
diff --git a/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5.html b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5.html
new file mode 100644
index 0000000000..44655ff420
--- /dev/null
+++ b/layout/reftests/async-scrolling/fixed-pos-scrolled-clip-5.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en-US"><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>The scrolled clip on the fixed element is not respected</title>
+
+</head><body><div style="
+ position: absolute;
+ top: 0;
+ left: 0;
+ clip: rect(auto auto auto auto);
+ width: 100%;
+ height: 200px;">
+
+ <div style="background-image: linear-gradient(lime, lime);
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ transform: translateZ(0px)">
+ </div>
+
+</div>
+</body></html>
diff --git a/layout/reftests/async-scrolling/group-opacity-surface-size-1-ref.html b/layout/reftests/async-scrolling/group-opacity-surface-size-1-ref.html
new file mode 100644
index 0000000000..12b6ee367a
--- /dev/null
+++ b/layout/reftests/async-scrolling/group-opacity-surface-size-1-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<style>
+
+body {
+ margin: 0;
+ overflow: hidden;
+}
+
+.opacity {
+ opacity: 0.8;
+}
+
+.box {
+ left: 0;
+ top: 200px;
+ width: 200px;
+ height: 200px;
+}
+
+.absolute {
+ position: absolute;
+ background: green;
+ top: 100px;
+}
+
+.fixed {
+ position: absolute;
+ background: blue;
+}
+
+</style>
+
+<div class="opacity">
+ <div class="box absolute"></div>
+ <div class="box fixed"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/group-opacity-surface-size-1.html b/layout/reftests/async-scrolling/group-opacity-surface-size-1.html
new file mode 100644
index 0000000000..c8562222ba
--- /dev/null
+++ b/layout/reftests/async-scrolling/group-opacity-surface-size-1.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+<style>
+
+html {
+ scrollbar-width: none;
+}
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.opacity {
+ opacity: 0.8;
+}
+
+.box {
+ left: 0;
+ top: 200px;
+ width: 200px;
+ height: 200px;
+}
+
+.absolute {
+ position: absolute;
+ background: green;
+}
+
+.fixed {
+ position: fixed;
+ background: blue;
+}
+
+</style>
+
+<div class="opacity">
+ <div class="box absolute"></div>
+ <div class="box fixed"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/iframe-1-ref.html b/layout/reftests/async-scrolling/iframe-1-ref.html
new file mode 100644
index 0000000000..76537c52c1
--- /dev/null
+++ b/layout/reftests/async-scrolling/iframe-1-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<iframe style="width:300px; height:600px; border:2px solid blue"
+ srcdoc="<!DOCTYPE HTML>
+ <html style='overflow:hidden'>
+ <div style='height:450px'></div>
+ <div style='height:200px; background:purple'>
+ <div style='display:inline-block; width:20px; height:20px; background:yellow;'></div>
+ </div>"></iframe>
diff --git a/layout/reftests/async-scrolling/iframe-1.html b/layout/reftests/async-scrolling/iframe-1.html
new file mode 100644
index 0000000000..5d6406f5a7
--- /dev/null
+++ b/layout/reftests/async-scrolling/iframe-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+<iframe style="width:300px; height:600px; border:2px solid blue"
+ srcdoc="<!DOCTYPE HTML>
+ <html reftest-displayport-x='0' reftest-displayport-y='0'
+ reftest-displayport-w='800' reftest-displayport-h='2000'
+ reftest-async-scroll-x='0' reftest-async-scroll-y='50' style='scrollbar-width: none'>
+ <div style='height:500px'></div>
+ <div style='height:200px; background:purple'>
+ <div style='display:inline-block; width:20px; height:20px; background:yellow;'></div>
+ </div>"></iframe>
diff --git a/layout/reftests/async-scrolling/nested-1-ref.html b/layout/reftests/async-scrolling/nested-1-ref.html
new file mode 100644
index 0000000000..2ad0568e19
--- /dev/null
+++ b/layout/reftests/async-scrolling/nested-1-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:500px; overflow:hidden; border:2px solid black">
+ <div style="width:300px; height:800px; overflow:hidden; border:2px solid blue; margin-top:-50px">
+ <div style="height:450px"></div>
+ <div style="height:200px; background:purple"></div>
+ </div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/nested-1.html b/layout/reftests/async-scrolling/nested-1.html
new file mode 100644
index 0000000000..953fe0c6f8
--- /dev/null
+++ b/layout/reftests/async-scrolling/nested-1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <!-- Test that nested active scrolling elements work -->
+ <div style="width:400px; height:500px; overflow:scroll; scrollbar-width: none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="width:300px; height:800px; overflow:scroll; scrollbar-width: none; border:2px solid blue"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="height:500px"></div>
+ <div style="height:200px; background:purple"></div>
+ <div style="height:500px"></div>
+ </div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/nested-2-ref.html b/layout/reftests/async-scrolling/nested-2-ref.html
new file mode 100644
index 0000000000..10ef23745e
--- /dev/null
+++ b/layout/reftests/async-scrolling/nested-2-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:500px; overflow:hidden; border:2px solid black">
+ <div style="width:300px; height:100px; overflow:hidden; border:2px solid blue; margin-top: 50px">
+ <div style="height:200px; background:purple"></div>
+ </div>
+ <div class="filler" style="height: 1000px"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/nested-2.html b/layout/reftests/async-scrolling/nested-2.html
new file mode 100644
index 0000000000..714761ab0b
--- /dev/null
+++ b/layout/reftests/async-scrolling/nested-2.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <!-- Test that nested active scrolling elements work -->
+ <div style="width:400px; height:500px; overflow:scroll; scrollbar-width: none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="width:300px; height:100px; overflow:scroll; scrollbar-width: none; border:2px solid blue; margin-top: 100px"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+ <div style="height:200px; background:purple"></div>
+ </div>
+ <div class="filler" style="height: 1000px"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/no-overscroll-ref.html b/layout/reftests/async-scrolling/no-overscroll-ref.html
new file mode 100644
index 0000000000..e6c2a479f1
--- /dev/null
+++ b/layout/reftests/async-scrolling/no-overscroll-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/offscreen-clipped-blendmode-1.html b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-1.html
new file mode 100644
index 0000000000..64795e5cfd
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-1.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1200">
+<meta charset="utf-8">
+<title>Scrolled blend mode</title>
+
+<style>
+
+body {
+ margin: 0;
+ padding: 100px;
+ height: 4000px;
+ background: white;
+}
+
+#outer {
+ height: 4000px;
+ overflow: hidden;
+}
+
+#inner-contents {
+ border: 1px solid black;
+ box-sizing: border-box;
+ width: 50px;
+ height: 50px;
+ mix-blend-mode: multiply;
+ margin-top: 1400px;
+}
+
+</style>
+
+<div id="outer">
+ <div id="inner">
+ <div id="inner-contents"></div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/offscreen-clipped-blendmode-2.html b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-2.html
new file mode 100644
index 0000000000..d85dc23e69
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1200">
+<meta charset="utf-8">
+<title>Scrolled blend mode</title>
+
+<style>
+
+body {
+ margin: 0;
+ padding: 100px;
+ height: 4000px;
+ background: white;
+}
+
+#outer {
+ height: 4000px;
+ overflow: hidden;
+}
+
+#inner {
+ transform: translateX(0);
+}
+
+#inner-contents {
+ border: 1px solid black;
+ box-sizing: border-box;
+ width: 50px;
+ height: 50px;
+ mix-blend-mode: multiply;
+ margin-top: 1400px;
+}
+
+</style>
+
+<div id="outer">
+ <div id="inner">
+ <div id="inner-contents"></div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/offscreen-clipped-blendmode-3.html b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-3.html
new file mode 100644
index 0000000000..e128e29872
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-3.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1200">
+<meta charset="utf-8">
+<title>Scrolled blend mode</title>
+
+<style>
+
+body {
+ margin: 0;
+ padding: 100px;
+ height: 4000px;
+ background: white;
+}
+
+#outer {
+ height: 4000px;
+ overflow: hidden;
+}
+
+#inner-contents {
+ border: 1px solid black;
+ box-sizing: border-box;
+ width: 50px;
+ height: 50px;
+ mix-blend-mode: multiply;
+ margin-top: 1400px;
+ transform: translateX(0);
+}
+
+</style>
+
+<div id="outer">
+ <div id="inner">
+ <div id="inner-contents"></div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/offscreen-clipped-blendmode-4.html b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-4.html
new file mode 100644
index 0000000000..8834747244
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-4.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="1200">
+<meta charset="utf-8">
+<title>Scrolled blend mode</title>
+
+<style>
+
+body {
+ margin: 0;
+ padding: 100px;
+ height: 4000px;
+ background: white;
+}
+
+#outer {
+ height: 4000px;
+ overflow: hidden;
+}
+
+#inner {
+ transform: translateX(0);
+}
+
+#inner-contents {
+ border: 1px solid black;
+ box-sizing: border-box;
+ width: 50px;
+ height: 50px;
+ mix-blend-mode: multiply;
+ margin-top: 1400px;
+ transform: translateX(0);
+}
+
+</style>
+
+<div id="outer">
+ <div id="inner">
+ <div id="inner-contents"></div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/offscreen-clipped-blendmode-ref.html b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-ref.html
new file mode 100644
index 0000000000..65660c6ca7
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-clipped-blendmode-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Scrolled blend mode</title>
+
+<style>
+
+body {
+ margin: 0;
+ padding: 100px;
+ height: 4000px;
+ background: white;
+}
+
+#inner-contents {
+ border: 1px solid black;
+ box-sizing: border-box;
+ width: 50px;
+ height: 50px;
+ margin-top: 1400px;
+}
+
+</style>
+
+<div id="inner-contents"></div>
+
+<script>
+
+document.documentElement.scrollTop = 1200;
+
+</script>
diff --git a/layout/reftests/async-scrolling/offscreen-prerendered-active-opacity-ref.html b/layout/reftests/async-scrolling/offscreen-prerendered-active-opacity-ref.html
new file mode 100644
index 0000000000..da251e5aaf
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-prerendered-active-opacity-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<title>Reference: Active opacity should be rendered if it's inside the display port, even if it's currently offscreen</title>
+
+<style>
+
+#scrollbox {
+ border: 1px solid black;
+ width: 200px;
+ height: 200px;
+ overflow: hidden;
+}
+
+#scrolledContent {
+ height: 1000px;
+}
+
+#opacity {
+ will-change: opacity;
+ opacity: 0.5;
+ margin-top: 250px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid blue;
+}
+
+
+</style>
+
+<div id="scrollbox">
+ <div id="scrolledContent">
+ <div id="opacity"></div>
+ </div>
+</div>
+
+<script>
+
+document.getElementById("scrollbox").scrollTop = 150;
+
+</script>
diff --git a/layout/reftests/async-scrolling/offscreen-prerendered-active-opacity.html b/layout/reftests/async-scrolling/offscreen-prerendered-active-opacity.html
new file mode 100644
index 0000000000..b89d5cd130
--- /dev/null
+++ b/layout/reftests/async-scrolling/offscreen-prerendered-active-opacity.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<meta charset="utf-8">
+<title>Active opacity should be rendered if it's inside the display port, even if it's currently offscreen</title>
+
+<style>
+
+.scrollbox {
+ border: 1px solid black;
+ width: 200px;
+ height: 200px;
+ overflow: scroll;
+ scrollbar-width: none;
+}
+
+.scrolledContent {
+ height: 1000px;
+}
+
+.opacity {
+ will-change: opacity;
+ opacity: 0.5;
+ margin-top: 250px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid blue;
+}
+
+
+</style>
+
+<div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="200" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="150">
+ <div class="scrolledContent">
+ <div class="opacity"></div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/opaque-fractional-displayport-1.html b/layout/reftests/async-scrolling/opaque-fractional-displayport-1.html
new file mode 100644
index 0000000000..8a73a7f309
--- /dev/null
+++ b/layout/reftests/async-scrolling/opaque-fractional-displayport-1.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Make sure the scrolled layer is opaque even if the scrolled area is fractional</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+.scrollbox {
+ margin: 50px;
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+
+ /* Make the background "non-uniform" so that the scrolled layer does not
+ * pull up a background color. */
+ background: linear-gradient(to bottom, white, transparent);
+}
+
+.scrolled-contents {
+ height: 300.2px;
+ background-color: lime;
+ box-sizing: border-box;
+}
+
+.transparent-overlap-of-fractional-edge {
+ margin: 0 20px;
+ height: 40px;
+ /* This element has a box-shadow that overlaps the bottom of the scrolled
+ * area. Box shadows do not expand the scrollable area. */
+ box-shadow: 0 280px rgba(0, 0, 255, 0.5);
+}
+
+</style>
+
+<body>
+
+<div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="200" reftest-displayport-h="300.2"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+ <div class="scrolled-contents">
+ <div class="transparent-overlap-of-fractional-edge reftest-opaque-layer">
+ <!-- This element has the magic "reftest-opaque-layer" class which
+ constitutes the actual test here. -->
+ </div>
+ </div>
+</div>
diff --git a/layout/reftests/async-scrolling/opaque-fractional-displayport-2.html b/layout/reftests/async-scrolling/opaque-fractional-displayport-2.html
new file mode 100644
index 0000000000..ddcac0fe85
--- /dev/null
+++ b/layout/reftests/async-scrolling/opaque-fractional-displayport-2.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Make sure the scrolled layer is opaque even if the scrolled area is fractional</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+.scrollbox {
+ margin: 50px;
+ width: 200px;
+ height: 200px;
+ overflow: auto;
+
+ /* Make the background "non-uniform" so that the scrolled layer does not
+ * pull up a background color. */
+ background: linear-gradient(to bottom, white, transparent);
+}
+
+.scrolled-contents {
+ height: 300.2px;
+ background-color: lime;
+ box-sizing: border-box;
+ border: 1px solid lime;
+}
+
+.transparent-overlap-of-fractional-edge {
+ margin: -10px 20px 0;
+ height: 40px;
+ background-color: rgba(0, 0, 255, 0.5);
+}
+
+</style>
+
+<body>
+
+<div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="-100.2"
+ reftest-displayport-w="200" reftest-displayport-h="300.2"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+ <div class="scrolled-contents">
+ <div class="transparent-overlap-of-fractional-edge reftest-opaque-layer">
+ <!-- This element has the magic "reftest-opaque-layer" class which
+ constitutes the actual test here. -->
+ </div>
+ </div>
+</div>
+
+<script>
+
+document.querySelector(".scrollbox").scrollTop = 100000; /* will end up at 100.2 */
+
+</script>
diff --git a/layout/reftests/async-scrolling/overscroll-disabled.html b/layout/reftests/async-scrolling/overscroll-disabled.html
new file mode 100644
index 0000000000..3c4927c9d0
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-disabled.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a viewport is rendered
+ as having the content create a gutter, and that
+ the overscroll is reduced by some factor such that
+ a 100px scroll must produce a rendered translation of less than
+ 100px.
+
+ Current overscroll physics mean that an instantaneous overscroll
+ by 200px produces an 8px gutter. This is governed by the logic in
+ Axis::ApplyResistance(); if that logic is changed, this test will
+ need to be modified to account for the new result.
+ -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-fixed-iframe-overscroll.html b/layout/reftests/async-scrolling/overscroll-fixed-iframe-overscroll.html
new file mode 100644
index 0000000000..d4af4f2235
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-fixed-iframe-overscroll.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0px;
+ padding: 0px;
+ border: 0px;
+ }
+ iframe {
+ width: 100%;
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+ border: 0px;
+ display: block;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a iframe does not
+ cause the fixed item in the iframe to participate in the
+ transform.
+ -->
+ <iframe src="data:text/html,
+ <!DOCTYPE HTML>
+ <html reftest-displayport-x='0' reftest-displayport-y='0'
+ reftest-displayport-w='800' reftest-displayport-h='2000'
+ reftest-async-scroll-x='0' reftest-async-scroll-y='-200'
+ style='scrollbar-width:none'>
+ <body style='padding: 0; margin: 0; border: 0'>
+ <div style='position: fixed; padding: 0; margin: 0; border: 0; background: green; width: 200px; height: 200px'>
+ </div>
+ </body>
+ </html>
+ ">
+ </iframe>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-fixed-iframe.html b/layout/reftests/async-scrolling/overscroll-fixed-iframe.html
new file mode 100644
index 0000000000..d2e55cf645
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-fixed-iframe.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0px;
+ padding: 0px;
+ border: 0px;
+ }
+ iframe {
+ width: 100%;
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+ border: 0px;
+ display: block;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a viewport is
+ rendered as having the content create a gutter, and that
+ the overscroll is reduced by some factor such that
+ a 100px scroll must produce a rendered translation of less than
+ 100px.
+
+ Current overscroll physics mean that an instantaneous overscroll
+ by 200px produces an 8px gutter. This is governed by the logic in
+ Axis::ApplyResistance(); if that logic is changed, this test will
+ need to be modified to account for the new result.
+ -->
+ <iframe src="data:text/html,
+ <!DOCTYPE HTML>
+ <html reftest-displayport-x='0' reftest-displayport-y='0'
+ reftest-displayport-w='800' reftest-displayport-h='2000'
+ style='scrollbar-width:none'>
+ <body style='padding: 0; margin: 0; border: 0'>
+ <div style='position: fixed; padding: 0; margin: 0; border: 0; background: green; width: 200px; height: 200px'>
+ </div>
+ </body>
+ </html>
+ ">
+ </iframe>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-fixed-transform.html b/layout/reftests/async-scrolling/overscroll-fixed-transform.html
new file mode 100644
index 0000000000..95eab157f0
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-fixed-transform.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div.container {
+ overflow: scroll;
+ width: 100%;
+ height: 100%;
+ transform: translate(0px);
+ scrollbar-width: none;
+ }
+ div.fixed {
+ position: fixed;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a transformed container is
+ rendered as having the content create a gutter, and that
+ the overscroll is reduced by some factor such that
+ a 100px scroll must produce a rendered translation of less than
+ 100px.
+
+ Current overscroll physics mean that an instantaneous overscroll
+ by 200px produces an 8px gutter. This is governed by the logic in
+ Axis::ApplyResistance(); if that logic is changed, this test will
+ need to be modified to account for the new result.
+ -->
+ <div class="container">
+ <div class="fixed">
+ </div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-fixed.html b/layout/reftests/async-scrolling/overscroll-fixed.html
new file mode 100644
index 0000000000..68410fffcf
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a viewport does not
+ cause a position fixed element to be transformed if the position
+ fixed element's containing block is the current viewport.
+ -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-ref.html b/layout/reftests/async-scrolling/overscroll-ref.html
new file mode 100644
index 0000000000..45e7535e64
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 8px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-scrollbar-ref.html b/layout/reftests/async-scrolling/overscroll-scrollbar-ref.html
new file mode 100644
index 0000000000..75a9bfeab6
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-scrollbar-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ body {
+ /* The 3028 here was arrived at experimentally to match to
+ produce a scrollbar of approximately the same length as
+ the one of the test page squished by the overscroll. */
+ height: 3028px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 8px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-scrollbar.html b/layout/reftests/async-scrolling/overscroll-scrollbar.html
new file mode 100644
index 0000000000..ab567ecfc0
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-scrollbar.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+<head>
+ <style>
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a viewport is rendered
+ as having the content create a gutter, and that
+ the overscroll is reduced by some factor such that
+ a 100px scroll must produce a rendered translation of less than
+ 100px.
+
+ Current overscroll physics mean that an instantaneous overscroll
+ by 200px produces an 8px gutter. This is governed by the logic in
+ Axis::ApplyResistance(); if that logic is changed, this test will
+ need to be modified to account for the new result.
+ -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll-subframe.html b/layout/reftests/async-scrolling/overscroll-subframe.html
new file mode 100644
index 0000000000..752253a4c7
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll-subframe.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<head>
+ <style>
+ * {
+ scrollbar-width: none;
+ }
+ body {
+ margin: 0;
+ }
+ #scroller {
+ overflow: auto;
+ width: 400px;
+ height: 400px;
+ }
+ #content {
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ #spacer {
+ height: 2000px;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a viewport is rendered
+ as having the content create a gutter, and that
+ the overscroll is reduced by some factor such that
+ a 100px scroll must produce a rendered translation of less than
+ 100px.
+
+ Current overscroll physics mean that an instantaneous overscroll
+ by 200px produces an 8px gutter. This is governed by the logic in
+ Axis::ApplyResistance(); if that logic is changed, this test will
+ need to be modified to account for the new result.
+ -->
+ <div id="scroller"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+ <div id="content"></div>
+ <div id="spacer"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/overscroll.html b/layout/reftests/async-scrolling/overscroll.html
new file mode 100644
index 0000000000..3c4927c9d0
--- /dev/null
+++ b/layout/reftests/async-scrolling/overscroll.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-200">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background: green;
+ }
+ </style>
+</head>
+<body >
+ <!-- Test that an overscroll past one end of a viewport is rendered
+ as having the content create a gutter, and that
+ the overscroll is reduced by some factor such that
+ a 100px scroll must produce a rendered translation of less than
+ 100px.
+
+ Current overscroll physics mean that an instantaneous overscroll
+ by 200px produces an 8px gutter. This is governed by the logic in
+ Axis::ApplyResistance(); if that logic is changed, this test will
+ need to be modified to account for the new result.
+ -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-1-ref.html b/layout/reftests/async-scrolling/perspective-scrolling-1-ref.html
new file mode 100644
index 0000000000..433aa7abb4
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-1-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Perspective scrolling</title>
+
+<style>
+
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ height: 100%;
+ perspective: 1px;
+ overflow: auto;
+ margin: 0;
+}
+
+div {
+ height: 4000px;
+ margin: 200px 100px;
+ border: 10px solid black;
+}
+
+</style>
+
+<div></div>
+
+<script>
+
+document.body.scrollTop = 100;
+
+</script>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-1.html b/layout/reftests/async-scrolling/perspective-scrolling-1.html
new file mode 100644
index 0000000000..cab2e4f8c4
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-1.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Perspective scrolling</title>
+
+<style>
+
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ height: 100%;
+ perspective: 1px;
+ overflow: auto;
+ margin: 0;
+}
+
+div {
+ transform-style: preserve-3d;
+ height: 4000px;
+ margin: 200px 100px;
+ border: 10px solid black;
+}
+
+</style>
+
+<body reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+
+<div></div>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-2-ref.html b/layout/reftests/async-scrolling/perspective-scrolling-2-ref.html
new file mode 100644
index 0000000000..720fbfa8df
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-2-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Perspective in unscrolled state</title>
+
+<style>
+
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ height: 100%;
+ perspective: 1px;
+ overflow: auto;
+ margin: 0;
+}
+
+.transformed {
+ margin: 200px 100px;
+ width: 200px;
+ height: 200px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<div class="transformed"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-2.html b/layout/reftests/async-scrolling/perspective-scrolling-2.html
new file mode 100644
index 0000000000..e2d7c86669
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-2.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Perspective in unscrolled state</title>
+
+<style>
+
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ margin: 0;
+ height: 100%;
+ perspective: 1px;
+ perspective-origin: top left;
+ overflow: auto;
+}
+
+.transformed {
+ transform: translateZ(-1px) scale(2);
+ transform-origin: -100px -200px;
+ margin: 200px 100px;
+ width: 200px;
+ height: 200px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<body reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0"> <!-- no async scrolling -->
+
+<div class="transformed"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-3-ref.html b/layout/reftests/async-scrolling/perspective-scrolling-3-ref.html
new file mode 100644
index 0000000000..9c8474d6c0
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-3-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Perspective in scrolled state</title>
+
+<style>
+
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ height: 100%;
+ perspective: 1px;
+ overflow: auto;
+ margin: 0;
+}
+
+.transformed {
+ margin: 300px 100px 100px;
+ width: 200px;
+ height: 200px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<div class="transformed"></div>
+<div class="spacer"></div>
+
+<script>
+
+document.body.scrollTop = 200;
+
+</script>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-3.html b/layout/reftests/async-scrolling/perspective-scrolling-3.html
new file mode 100644
index 0000000000..8211c52afb
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-3.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Perspective in scrolled state</title>
+
+<style>
+
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ margin: 0;
+ height: 100%;
+ perspective: 1px;
+ perspective-origin: top left;
+ overflow: auto;
+}
+
+.transformed {
+ transform: translateZ(-1px) scale(2);
+ transform-origin: -100px -200px;
+ margin: 200px 100px;
+ width: 200px;
+ height: 200px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<body reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="200">
+
+<div class="transformed"></div>
+<div class="spacer"></div>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-4-ref.html b/layout/reftests/async-scrolling/perspective-scrolling-4-ref.html
new file mode 100644
index 0000000000..4f5b1fc010
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-4-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Reference: Perspective scrolling with nested clips</title>
+
+<style>
+
+html {
+ padding: 50px 0 3000px;
+}
+
+body {
+ margin: 0;
+}
+
+.scrollbox {
+ width: 600px;
+ height: 500px;
+ perspective: 1px;
+ overflow: auto;
+}
+
+.transformed {
+ will-change: transform;
+ width: 200px;
+ height: 200px;
+ margin: 200px 100px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<div class="scrollbox">
+ <div class="transformed"></div>
+ <div class="spacer"></div>
+</div>
+
+<script>
+document.documentElement.scrollTop = 250;
+</script>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-4.html b/layout/reftests/async-scrolling/perspective-scrolling-4.html
new file mode 100644
index 0000000000..49453d74df
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-4.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="250">
+<meta charset="utf-8">
+<title>Perspective scrolling with nested clips</title>
+
+<style>
+
+html {
+ padding: 50px 0 3000px;
+}
+
+body {
+ margin: 0;
+}
+
+.scrollbox {
+ width: 600px;
+ height: 500px;
+ perspective: 1px;
+ overflow: auto;
+}
+
+.transformed {
+ will-change: transform;
+ width: 200px;
+ height: 200px;
+ margin: 200px 100px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="600" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+
+ <div class="transformed"></div>
+ <div class="spacer"></div>
+
+</div>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-5-ref.html b/layout/reftests/async-scrolling/perspective-scrolling-5-ref.html
new file mode 100644
index 0000000000..dc41f00d04
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-5-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Reference</title>
+<style>
+ * { margin: 0; padding: 0 }
+
+ div {
+ width: 200px;
+ height: 200px;
+ background-color: lime;
+ }
+</style>
+<div></div>
diff --git a/layout/reftests/async-scrolling/perspective-scrolling-5.html b/layout/reftests/async-scrolling/perspective-scrolling-5.html
new file mode 100644
index 0000000000..cfbf2d2228
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-5.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Perspective scrolling</title>
+<style>
+html {
+ height: 100%;
+ overflow: hidden;
+}
+
+body {
+ overflow: auto;
+ height: 100%;
+ scrollbar-width: none;
+ margin: 0;
+}
+
+.scene {
+ position: relative;
+ width: 200px;
+ height: 200px;
+ perspective: 100px;
+ transform-style: preserve-3d;
+}
+
+.face {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ top: 0;
+ left: 0;
+}
+
+.front {
+ background-color: lime;
+}
+
+/*
+ * This one should never be visible, and should be always
+ * behind the front face.
+ */
+.back {
+ width: 400px;
+ height: 400px;
+ top: -100px;
+ left: -100px;
+ transform: translateZ(-100px);
+ background-color: red;
+}
+</style>
+
+<body reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="200">
+<div style="height: 200px"></div>
+<div class="scene">
+ <div class="face front"></div>
+ <div class="face back"></div>
+</div>
+<div style="height: 5000px"></div>
diff --git a/layout/reftests/async-scrolling/position-fixed-1-ref.html b/layout/reftests/async-scrolling/position-fixed-1-ref.html
new file mode 100644
index 0000000000..b373cc1142
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="position:fixed; background:blue; top:0; left:0; width:200px; height:100px"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-1.html b/layout/reftests/async-scrolling/position-fixed-1.html
new file mode 100644
index 0000000000..d30ada3c23
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px">
+ <!-- Test that position:fixed content stays fixed when we async-scroll -->
+ <div style="position:fixed; background:blue; top:0; left:0; width:200px; height:100px"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-2-ref.html b/layout/reftests/async-scrolling/position-fixed-2-ref.html
new file mode 100644
index 0000000000..8804dd67b4
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-2-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px">
+ <div style="position:absolute; top:-25px; left:0; width:100px; height:200px; background:yellow; z-index:1"></div>
+ <div style="position:fixed; background:blue; top:0; left:0; width:200px; height:100px">
+ <div style="position:absolute; background:cyan; top:40px; left:0; width:50px; height:300px;"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-2.html b/layout/reftests/async-scrolling/position-fixed-2.html
new file mode 100644
index 0000000000..434c73aa2a
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px">
+ <!-- test that a fixed-pos element whose contents are interleaved in z-order
+ with non-scrolling content works correctly with async scrolling -->
+ <div style="position:absolute; top:25px; left:0; width:100px; height:200px; background:yellow; z-index:1"></div>
+ <div style="position:fixed; background:blue; top:0; left:0; width:200px; height:100px">
+ <div style="position:absolute; background:cyan; top:40px; left:0; width:50px; height:300px;"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-1-ref.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-1-ref.html
new file mode 100644
index 0000000000..f03a8f8131
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-1-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=2.0">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ top: -50px;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-1.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-1.html
new file mode 100644
index 0000000000..419bd74208
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ top: 0;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <!-- Test that position:fixed elements are attached to the layout viewport
+ instead of the visual viewport.
+
+ An async scroll of 50 CSS pixels will scroll the visual viewport by 100
+ screen pixels (since async zoom is set to 2.0) and result in the top
+ half of the div being scrolled out of view. -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-2-ref.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-2-ref.html
new file mode 100644
index 0000000000..324c5f5534
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-2-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=2.0">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 0;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-2.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-2.html
new file mode 100644
index 0000000000..8d672ecad3
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-2.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="reftest-wait"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-50"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ top: 0;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body onload="scrollTo(0, 1000); document.documentElement.classList.remove('reftest-wait');">
+ <!-- Test that position:fixed elements scroll with the layout viewport.
+
+ Scroll the window (i.e., the layout viewport) to (0, 1000). An async
+ scroll of -50 CSS pixels will move both the layout and visual viewport
+ up by 100 screen pixels (since async zoom is set to 2.0). The div should
+ remain at top-left corner of the layout viewport. -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-3-ref.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-3-ref.html
new file mode 100644
index 0000000000..00dc290aca
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-3-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=2.0">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ height: 100px;
+ width: 100px;
+ background: blue;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-3.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-3.html
new file mode 100644
index 0000000000..112926c2da
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-3.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ height: 100px;
+ width: 100px;
+ background: blue;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-4-ref.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-4-ref.html
new file mode 100644
index 0000000000..3155a387ce
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-4-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=2.0">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ height: 100px;
+ width: 100px;
+ }
+ div.top-left {
+ top: 20px;
+ left: 20px;
+ background: red;
+ }
+ div.top-right {
+ top: 20px;
+ right: 20px;
+ background: blue;
+ }
+ div.bottom-left {
+ bottom: 20px;
+ left: 20px;
+ background: green;
+ }
+ div.bottom-right {
+ bottom: 20px;
+ right: 20px;
+ background: purple;
+ }
+ </style>
+</head>
+<body>
+ <div class="top-left"></div>
+ <div class="top-right"></div>
+ <div class="bottom-left"></div>
+ <div class="bottom-right"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-async-zoom-4.html b/layout/reftests/async-scrolling/position-fixed-async-zoom-4.html
new file mode 100644
index 0000000000..6d425e3468
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-async-zoom-4.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ height: 100px;
+ width: 100px;
+ }
+ div.top-left {
+ top: 20px;
+ left: 20px;
+ background: red;
+ }
+ div.top-right {
+ top: 20px;
+ right: 20px;
+ background: blue;
+ }
+ div.bottom-left {
+ bottom: 20px;
+ left: 20px;
+ background: green;
+ }
+ div.bottom-right {
+ bottom: 20px;
+ right: 20px;
+ background: purple;
+ }
+ </style>
+</head>
+<body>
+ <div class="top-left"></div>
+ <div class="top-right"></div>
+ <div class="bottom-left"></div>
+ <div class="bottom-right"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-body-ref.html b/layout/reftests/async-scrolling/position-fixed-body-ref.html
new file mode 100644
index 0000000000..4d1d74b175
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-body-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<style>
+body {
+ height: 100vh;
+ margin: 0px;
+}
+#scrollbox {
+ width: 100%;
+ height: 100%;
+ overflow: scroll;
+ scrollbar-width: none;
+}
+#scrolledContents {
+ height: 10000px;
+ background: radial-gradient(circle, blue 30%, transparent 0);
+ background-size: 80px 80px;
+}
+</style>
+<body>
+ <div id="scrollbox"
+ reftest-dislayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="20">
+ <div id="scrolledContents"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-body.html b/layout/reftests/async-scrolling/position-fixed-body.html
new file mode 100644
index 0000000000..7ae1122d72
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-body.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<style>
+body {
+ position: fixed;
+ margin: 0px;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+#scrollbox {
+ width: 100%;
+ height: 100%;
+ overflow: scroll;
+ scrollbar-width: none;
+}
+#scrolledContents {
+ height: 10000px;
+ background: radial-gradient(circle, blue 30%, transparent 0);
+ background-size: 80px 80px;
+}
+</style>
+<body>
+ <div id="scrollbox"
+ reftest-dislayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="20">
+ <div id="scrolledContents"></div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-cover-1-ref.html b/layout/reftests/async-scrolling/position-fixed-cover-1-ref.html
new file mode 100644
index 0000000000..9e4dbe95d3
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-cover-1-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px">
+ <div style="position:absolute; background:blue; top:300px; left:0; width:500px; height:200px;"></div>
+ <div style="position:absolute; background:black; top:0; left:0; width:500px; height:200px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-cover-1.html b/layout/reftests/async-scrolling/position-fixed-cover-1.html
new file mode 100644
index 0000000000..696655e678
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-cover-1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="400"
+ style="scrollbar-width:none">
+<body style="height:3000px">
+ <!-- Test that position:fixed content covered by scrolling content gets rendered
+ properly -->
+ <div style="position:fixed; background:blue; top:300px; left:0; width:500px; height:200px; z-index:1"></div>
+ <div style="position:absolute; background:black; top:200px; left:0; width:500px; height:400px; z-index:2"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-cover-2-ref.html b/layout/reftests/async-scrolling/position-fixed-cover-2-ref.html
new file mode 100644
index 0000000000..134ef72826
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-cover-2-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px">
+ <div style="position:absolute; background:black; top:0; left:0; width:500px; height:100px;"></div>
+ <div style="position:absolute; background:blue; top:200px; left:0; width:500px; height:400px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-cover-2.html b/layout/reftests/async-scrolling/position-fixed-cover-2.html
new file mode 100644
index 0000000000..295344cc5c
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-cover-2.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="400"
+ style="scrollbar-width:none">
+<body style="height:3000px">
+ <!-- Test that scrolling content covered by position-fixed content
+ gets rendered properly -->
+ <div style="position:absolute; background:black; top:300px; left:0; width:500px; height:200px; z-index:1"></div>
+ <div style="position:fixed; background:blue; top:200px; left:0; width:500px; height:400px; z-index:2"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-cover-3-ref.html b/layout/reftests/async-scrolling/position-fixed-cover-3-ref.html
new file mode 100644
index 0000000000..a8e706087f
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-cover-3-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body style="overflow:hidden; height:3000px">
+ <div style="position:absolute; background:blue; top:200px; left:0; width:500px; height:200px;"></div>
+ <div style="position:absolute; background:gray; top:100px; left:0; width:500px; height:200px;"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-cover-3.html b/layout/reftests/async-scrolling/position-fixed-cover-3.html
new file mode 100644
index 0000000000..7ed268cecf
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-cover-3.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="400"
+ style="scrollbar-width:none">
+<body style="height:3000px">
+ <!-- Test that scrolling content above position-fixed content but not
+ intersecting it doesn't get moved down to a layer below the
+ position-fixed content -->
+ <div style="position:absolute; background:black; top:0; left:0; width:500px; height:200px; z-index:1"></div>
+ <div style="position:fixed; background:blue; top:200px; left:0; width:500px; height:200px; z-index:2"></div>
+ <div style="position:absolute; background:gray; top:500px; left:0; width:500px; height:200px; z-index:3"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-iframe-1-ref.html b/layout/reftests/async-scrolling/position-fixed-iframe-1-ref.html
new file mode 100644
index 0000000000..b373cc1142
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-iframe-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="position:fixed; background:blue; top:0; left:0; width:200px; height:100px"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-iframe-1.html b/layout/reftests/async-scrolling/position-fixed-iframe-1.html
new file mode 100644
index 0000000000..c071ec7e16
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-iframe-1.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <!-- Test that position:fixed content stays fixed when we async-scroll -->
+ <iframe style="border:0; width:400px; height:400px;" src="data:text/html,
+ <!DOCTYPE HTML>
+ <html reftest-displayport-x='0' reftest-displayport-y='0'
+ reftest-displayport-w='800' reftest-displayport-h='2000'
+ reftest-async-scroll-x='0' reftest-async-scroll-y='50'
+ style='scrollbar-width:none'>
+ <body style='height:3000px'>
+ <div style='position:fixed; background:blue; top:0; left:0; width:200px; height:100px'></div>
+ <div style='background:red; margin-top:100px; width:100px; height:50px'></div>
+ </body>
+ </html>
+ "></iframe>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-iframe-2-ref.html b/layout/reftests/async-scrolling/position-fixed-iframe-2-ref.html
new file mode 100644
index 0000000000..b373cc1142
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-iframe-2-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="position:fixed; background:blue; top:0; left:0; width:200px; height:100px"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-iframe-2.html b/layout/reftests/async-scrolling/position-fixed-iframe-2.html
new file mode 100644
index 0000000000..513d9caabb
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-iframe-2.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="80"
+ style="scrollbar-width:none">
+<body style="height:3000px; margin:0;">
+ <!-- Test that position:fixed content stays fixed when we async-scroll -->
+ <iframe style="border:0; width:400px; height:400px; margin-top:80px;" src="data:text/html,
+ <!DOCTYPE HTML>
+ <html reftest-displayport-x='0' reftest-displayport-y='0'
+ reftest-displayport-w='800' reftest-displayport-h='2000'
+ reftest-async-scroll-x='0' reftest-async-scroll-y='50'
+ style='scrollbar-width:none'>
+ <body style='height:3000px'>
+ <div style='position:fixed; background:blue; top:0; left:0; width:200px; height:100px'></div>
+ <div style='background:red; margin-top:100px; width:100px; height:50px'></div>
+ </body>
+ </html>
+ "></iframe>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-in-scroll-container-ref.html b/layout/reftests/async-scrolling/position-fixed-in-scroll-container-ref.html
new file mode 100644
index 0000000000..3d2ba64eb1
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-in-scroll-container-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<style>
+
+body {
+ height: 10000px;
+}
+
+.outer-opacity {
+ opacity: 0.8;
+}
+
+.scrollbox {
+ border: 1px solid black;
+ width: 200px;
+ height: 400px;
+ overflow: hidden;
+}
+
+.inner-opacity {
+ height: 1000px;
+ opacity: 0.8;
+}
+
+.fixed {
+ background: blue;
+ width: 100px;
+ height: 100px;
+}
+
+</style>
+
+<div class="outer-opacity">
+ <div class="scrollbox">
+ <div class="inner-opacity">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</div>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-in-scroll-container.html b/layout/reftests/async-scrolling/position-fixed-in-scroll-container.html
new file mode 100644
index 0000000000..0874aa67a5
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-in-scroll-container.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<!-- In this test, the div |fixed| is fixed with respect to the
+ page's root scroll frame, but there's also a subframe |scrollbox|
+ which is async-scrolled and which generates a container layer
+ (because of the opacity), so that its async transform is on an
+ ancestor layer of |fixed|'s layer. We are testing that this
+ async transform is correctly unapplied to keep |fixed| fixed. -->
+<style>
+
+body {
+ height: 10000px;
+}
+
+.outer-opacity {
+ opacity: 0.8;
+}
+
+.scrollbox {
+ border: 1px solid black;
+ width: 200px;
+ height: 400px;
+ overflow: scroll;
+ scrollbar-width: none;
+}
+
+.inner-opacity {
+ height: 1000px;
+ opacity: 0.8;
+}
+
+.fixed {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ position: fixed;
+}
+
+</style>
+<div class="outer-opacity">
+ <div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="200" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div class="inner-opacity">
+ <div class="fixed"></div>
+ </div>
+ </div>
+</div>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-clip-path-ref.html b/layout/reftests/async-scrolling/position-fixed-inside-clip-path-ref.html
new file mode 100644
index 0000000000..6832fa2bf6
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-clip-path-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<style>
+ body {
+ height: 4000px;
+ margin: 0;
+ overflow: hidden;
+ }
+ #clip {
+ position: absolute;
+ top: 450px;
+ left: 300px;
+ background: red;
+ width: 400px;
+ height: 400px;
+ clip-path: inset(0);
+ }
+ #fixed {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(green, blue);
+ }
+</style>
+<div id="clip">
+ <div id="fixed"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-clip-path.html b/layout/reftests/async-scrolling/position-fixed-inside-clip-path.html
new file mode 100644
index 0000000000..2759f6c0cf
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-clip-path.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+<style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 4000px;
+ margin: 0;
+ }
+ #clip {
+ position: absolute;
+ top: 500px;
+ left: 300px;
+ background: red;
+ width: 400px;
+ height: 400px;
+ clip-path: inset(0);
+ }
+ #fixed {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(green, blue);
+ }
+</style>
+<div id="clip">
+ <div id="fixed"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-sticky-1-ref.html b/layout/reftests/async-scrolling/position-fixed-inside-sticky-1-ref.html
new file mode 100644
index 0000000000..8c48da5dbe
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-sticky-1-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+ height: 4000px;
+ margin: 0;
+ overflow: hidden;
+}
+#fixed {
+ position: fixed;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid blue;
+}
+</style>
+<div id="fixed"></div>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-sticky-1.html b/layout/reftests/async-scrolling/position-fixed-inside-sticky-1.html
new file mode 100644
index 0000000000..8d47c22155
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-sticky-1.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+<style>
+html {
+ scrollbar-width: none;
+}
+body {
+ height: 4000px;
+ margin: 0;
+}
+#sticky {
+ position: sticky;
+ top: -1000px; /* scrolls regularly until the top edge hits -1000px, then stays fixed */
+ height: 1200px;
+ border-bottom: 1px solid black;
+}
+#fixed {
+ position: fixed;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid blue;
+}
+</style>
+<div id="sticky">
+ <div id="fixed"></div>
+</div>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-sticky-2-ref.html b/layout/reftests/async-scrolling/position-fixed-inside-sticky-2-ref.html
new file mode 100644
index 0000000000..8c48da5dbe
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-sticky-2-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+ height: 4000px;
+ margin: 0;
+ overflow: hidden;
+}
+#fixed {
+ position: fixed;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid blue;
+}
+</style>
+<div id="fixed"></div>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-sticky-2.html b/layout/reftests/async-scrolling/position-fixed-inside-sticky-2.html
new file mode 100644
index 0000000000..af596f2a12
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-sticky-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+<style>
+html {
+ scrollbar-width: none;
+}
+body {
+ height: 4000px;
+ margin: 0;
+}
+#sticky {
+ position: sticky;
+ top: 25px; /* scrolls regularly until the top edge hits 25px, then stays fixed */
+ margin-top: 50px;
+ height: 1200px;
+ border-bottom: 1px solid black;
+}
+#fixed {
+ position: fixed;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid blue;
+}
+</style>
+<div id="sticky">
+ <div id="fixed"></div>
+</div>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-sticky-3-ref.html b/layout/reftests/async-scrolling/position-fixed-inside-sticky-3-ref.html
new file mode 100644
index 0000000000..88f0577aab
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-sticky-3-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+ height: 4000px;
+ margin: 0;
+ overflow: hidden;
+}
+#sticky {
+ position: sticky;
+ top: 0;
+ height: 60px;
+ background-color: blue;
+}
+</style>
+<body>
+<div id="sticky"></div>
+</body></html>
diff --git a/layout/reftests/async-scrolling/position-fixed-inside-sticky-3.html b/layout/reftests/async-scrolling/position-fixed-inside-sticky-3.html
new file mode 100644
index 0000000000..852561bdb5
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-sticky-3.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="300">
+<style>
+html {
+ scrollbar-width: none;
+}
+body {
+ height: 4000px;
+ margin: 0;
+}
+#sticky {
+ position: sticky;
+ top: 0;
+ height: 60px;
+ background-color: blue;
+}
+#fixed {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100px;
+ height: 100px;
+}
+</style>
+<body>
+<div style="height: 200px;"></div>
+<div id="sticky">
+ <div id="fixed"></div>
+</div>
+</body></html>
diff --git a/layout/reftests/async-scrolling/position-fixed-transformed-1-ref.html b/layout/reftests/async-scrolling/position-fixed-transformed-1-ref.html
new file mode 100644
index 0000000000..6cb0963031
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-transformed-1-ref.html
@@ -0,0 +1,21 @@
+<html>
+<head>
+<style>
+.fixedpos {
+ transform: translateX(0px);
+ position: fixed;
+ top: 0;
+ width: 100%;
+ height: 100px;
+ background: red;
+}
+.filler {
+ height: 4000px;
+}
+</style>
+</head>
+<body onload="scrollTo(0,200)">
+<div class="fixedpos"></div>
+<div class="filler"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-fixed-transformed-1.html b/layout/reftests/async-scrolling/position-fixed-transformed-1.html
new file mode 100644
index 0000000000..4f9cac419e
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-transformed-1.html
@@ -0,0 +1,23 @@
+<html reftest-async-scroll
+ reftest-async-scroll-x="0"
+ reftest-async-scroll-y="200">
+<head>
+<style>
+.fixedpos {
+ transform: translateX(0px);
+ position: fixed;
+ top: 0;
+ width: 100%;
+ height: 100px;
+ background: red;
+}
+.filler {
+ height: 4000px;
+}
+</style>
+</head>
+<body>
+<div class="fixedpos"></div>
+<div class="filler"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-async-zoom-1-ref.html b/layout/reftests/async-scrolling/position-sticky-async-zoom-1-ref.html
new file mode 100644
index 0000000000..f03a8f8131
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-async-zoom-1-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=2.0">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: fixed;
+ top: -50px;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-async-zoom-1.html b/layout/reftests/async-scrolling/position-sticky-async-zoom-1.html
new file mode 100644
index 0000000000..d0af0e8f1f
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-async-zoom-1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: sticky;
+ top: 0;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <!-- This test is identical to the position-fixed-async-zoom-1 test, but for
+ position:sticky elements. -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-async-zoom-2-ref.html b/layout/reftests/async-scrolling/position-sticky-async-zoom-2-ref.html
new file mode 100644
index 0000000000..324c5f5534
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-async-zoom-2-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=2.0">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: absolute;
+ top: 0;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-async-zoom-2.html b/layout/reftests/async-scrolling/position-sticky-async-zoom-2.html
new file mode 100644
index 0000000000..8d815439a9
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-async-zoom-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="-50"
+ reftest-async-zoom="2.0">
+<head>
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ body {
+ height: 3000px;
+ margin: 0;
+ }
+ div {
+ position: sticky;
+ top: 0;
+ width: 100px;
+ height: 100px;
+ background: green;
+ }
+ </style>
+</head>
+<body onload="scrollTo(0, 1000); document.documentElement.classList.remove('reftest-wait');">
+ <!-- This test is identical to the position-fixed-async-zoom-2 test, but for
+ position:sticky elements. -->
+ <div></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-bug1434250-ref.html b/layout/reftests/async-scrolling/position-sticky-bug1434250-ref.html
new file mode 100644
index 0000000000..153ca9f8dd
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-bug1434250-ref.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <style type="text/css" media="all">
+ body {
+ margin-top: 0;
+ overflow: hidden;
+ }
+ .container {
+ width: 500px;
+ background: #fcc;
+ height: 2000px;
+ }
+ .header {
+ position: sticky;
+ top: 0px;
+ background: #cfc;
+ height: 50px;
+ }
+ </style>
+ </head>
+ <body>
+ <div class='container'>
+ <div class='header'></div>
+ </div>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-bug1434250.html b/layout/reftests/async-scrolling/position-sticky-bug1434250.html
new file mode 100644
index 0000000000..740acb1516
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-bug1434250.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <head>
+ <meta charset='utf-8'>
+ <style type="text/css" media="all">
+ html {
+ scrollbar-width: none;
+ }
+ .container {
+ width: 500px;
+ background: #fcc;
+ height: 2000px;
+ }
+ .header {
+ position: sticky;
+ top: 0px;
+ background: #cfc;
+ height: 50px;
+ }
+ </style>
+ </head>
+ <body>
+ <div class='container'>
+ <div class='header'></div>
+ </div>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1-ref.html b/layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1-ref.html
new file mode 100644
index 0000000000..789a3138f2
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+
+<title>reference for: position:sticky item that's still visible while the rest of the scrollframe contents are checkerboarded</title>
+
+<style>
+html {
+ scrollbar-width: none;
+}
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+#fixed {
+ position: fixed;
+ top: 0;
+ height: 100px;
+ width: 100%;
+ background-color: green;
+}
+
+</style>
+
+<div id="fixed"></div>
+
+<script>
+document.scrollingElement.scrollTop = 2500;
+</script>
diff --git a/layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1.html b/layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1.html
new file mode 100644
index 0000000000..720114b909
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-in-checkerboard-land-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="2500">
+
+<title>position:sticky item that's still visible while the rest of the scrollframe contents are checkerboarded</title>
+
+<style>
+html {
+ scrollbar-width: none;
+}
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+#sticky_container {
+ margin-top: 100px;
+ height: 3000px;
+ background-image: linear-gradient(green, blue);
+}
+
+#sticky {
+ position: sticky;
+ top: 0;
+ height: 100px;
+ background-color: green;
+}
+
+</style>
+
+<div id="sticky_container">
+ <div id="sticky"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-1.html b/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-1.html
new file mode 100644
index 0000000000..a9e52cb744
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<div style="transform: translateY(10px); margin-top: 90px">
+<div style="overflow:scroll; height: 400px; width: 400px; background-color: yellow"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="400"
+ reftest-displayport-h="800"
+ reftest-async-scroll-x="0"
+ reftest-async-scroll-y="120">
+<div style="height: 800px">
+<div style="position:sticky; top: 0px; height: 20px; background-color: green"></div>
+</div>
+</div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-2.html b/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-2.html
new file mode 100644
index 0000000000..73944529d5
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<div style="transform: translateY(90px); margin-top: 10px">
+<div style="overflow:scroll; height: 400px; width: 400px; background-color: yellow"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="400"
+ reftest-displayport-h="800"
+ reftest-async-scroll-x="0"
+ reftest-async-scroll-y="120">
+<div style="height: 800px">
+<div style="position:sticky; top: 0px; height: 20px; background-color: green"></div>
+</div>
+</div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-ref.html b/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-ref.html
new file mode 100644
index 0000000000..0f03a8a766
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-in-transformed-scrollframe-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<div style="margin-top: 100px">
+<div id="scroller" style="overflow:scroll; height: 400px; width: 400px; background-color: yellow">
+<div style="height: 800px">
+<div style="position: relative; top: 120px; height: 20px; background-color: green"></div>
+</div>
+</div>
+</div>
+<script>
+ document.getElementById('scroller').scrollTop = 120;
+</script>
diff --git a/layout/reftests/async-scrolling/position-sticky-scrolled-clip-1-ref.html b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-1-ref.html
new file mode 100644
index 0000000000..c07e288f56
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-1-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+
+<title>Reference for: position:sticky with scrolled clip should correctly move the clip</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.halfBox {
+ position: absolute;
+ left: 0;
+ top: 100px;
+ width: 100px;
+ height: 50px;
+ box-sizing: border-box;
+ border: 1px solid black;
+ border-bottom: none;
+}
+
+</style>
+
+<div class="halfBox"></div>
+
+<script>
+
+document.documentElement.scrollTop = 100;
+
+</script>
diff --git a/layout/reftests/async-scrolling/position-sticky-scrolled-clip-1.html b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-1.html
new file mode 100644
index 0000000000..f547386fb6
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+
+<title>position:sticky with scrolled clip should correctly move the clip</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+ position: relative;
+}
+
+.absoluteClip {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100px;
+ height: 200px;
+ clip: rect(auto, auto, 150px, auto);
+}
+
+.sticky {
+ position: sticky;
+ top: 0;
+ box-sizing: border-box;
+ height: 100px;
+ border: 1px solid black;
+}
+
+</style>
+
+<div class="absoluteClip">
+ <div class="sticky"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-scrolled-clip-2-ref.html b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-2-ref.html
new file mode 100644
index 0000000000..12f2071728
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-2-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+
+<title>Reference for: position:sticky with scrolled clip should prerender everything and correctly move the clip</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+}
+
+.completeBox {
+ position: absolute;
+ left: 0;
+ top: 100px;
+ width: 100px;
+ height: 100px;
+ box-sizing: border-box;
+ border: 1px solid black;
+}
+
+</style>
+
+<div class="completeBox"></div>
+
+<script>
+
+document.documentElement.scrollTop = 100;
+
+</script>
diff --git a/layout/reftests/async-scrolling/position-sticky-scrolled-clip-2.html b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-2.html
new file mode 100644
index 0000000000..5ded43e5ed
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-scrolled-clip-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+
+<title>position:sticky with scrolled clip should prerender everything and correctly move the clip</title>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+ position: relative;
+}
+
+.absoluteClip {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100px;
+ height: 200px;
+ clip: rect(50px, auto, auto, auto);
+}
+
+.sticky {
+ position: sticky;
+ top: 0;
+ box-sizing: border-box;
+ height: 100px;
+ border: 1px solid black;
+}
+
+</style>
+
+<div class="absoluteClip">
+ <div class="sticky"></div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1-ref.html b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1-ref.html
new file mode 100644
index 0000000000..365c247fe0
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<div id="scroller" style="overflow:scroll; height: 400px; width: 400px">
+<div style="transform: translateY(10px); margin-top: 90px; background-color: yellow; height: 400px">
+<div style="position: relative; top: 30px; height: 20px; background-color: green"></div>
+</div>
+<div style="height: 400px">spacer</div>
+</div>
+<script>
+ document.getElementById('scroller').scrollTop = 120;
+</script>
diff --git a/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1.html b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1.html
new file mode 100644
index 0000000000..f1ccc63dec
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<div style="overflow:scroll; height: 400px; width: 400px"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="400"
+ reftest-displayport-h="890"
+ reftest-async-scroll-x="0"
+ reftest-async-scroll-y="120">
+<div style="transform: translateY(10px); margin-top: 90px; background-color: yellow; height: 400px">
+<div style="position:sticky; top: 0px; height: 20px; background-color: green"></div>
+</div>
+<div style="height: 400px">spacer</div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2-ref.html b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2-ref.html
new file mode 100644
index 0000000000..763a4a550a
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<div id="scroller" style="overflow:scroll; height: 400px; width: 400px">
+<div style="margin-top: 120px; background-color: yellow; height: 380px">
+<div style="height: 90px"></div>
+<div style="height: 20px; background-color: green"></div>
+</div>
+<div style="height: 310px"></div>
+</div>
+<script>
+ document.getElementById('scroller').scrollTop = 120;
+</script>
diff --git a/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2.html b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2.html
new file mode 100644
index 0000000000..ff0e050508
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-transformed-in-scrollframe-2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<div style="overflow:scroll; height: 400px; width: 400px"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="400"
+ reftest-displayport-h="890"
+ reftest-async-scroll-x="0"
+ reftest-async-scroll-y="120">
+<div style="transform: translateY(90px); margin-top: 10px; background-color: yellow; height: 400px">
+<div style="position:sticky; top: 0px; height: 20px; background-color: green"></div>
+</div>
+<div style="height: 400px">spacer</div>
+</div>
diff --git a/layout/reftests/async-scrolling/position-sticky-transformed-ref.html b/layout/reftests/async-scrolling/position-sticky-transformed-ref.html
new file mode 100644
index 0000000000..19a91e7cd1
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-transformed-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body style="height:3000px; margin: 0px; overflow: hidden">
+ <div style="position:sticky; transform: rotateX(30deg) rotateY(10deg); background:blue; top:0; left:0; width:200px; height:100px"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/position-sticky-transformed.html b/layout/reftests/async-scrolling/position-sticky-transformed.html
new file mode 100644
index 0000000000..29cd778974
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-sticky-transformed.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width: none">
+<body style="height:3000px; margin: 0px;">
+ <div style="position:sticky; transform: rotateX(30deg) rotateY(10deg); background:blue; top:0; left:0; width:200px; height:100px"></div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/reftest.list b/layout/reftests/async-scrolling/reftest.list
new file mode 100644
index 0000000000..29ef866827
--- /dev/null
+++ b/layout/reftests/async-scrolling/reftest.list
@@ -0,0 +1,190 @@
+skip-if(!asyncPan) == bg-fixed-1.html bg-fixed-1-ref.html
+skip-if(!asyncPan) == bg-fixed-cover-1.html bg-fixed-cover-1-ref.html
+skip-if(!asyncPan) == bg-fixed-cover-2.html bg-fixed-cover-2-ref.html
+skip-if(!asyncPan) == bg-fixed-cover-3.html bg-fixed-cover-3-ref.html
+skip-if(!asyncPan) == bg-fixed-child.html bg-fixed-child-ref.html
+skip-if(!asyncPan) == bg-fixed-child-clip-1.html bg-fixed-child-clip-ref.html
+skip-if(!asyncPan) == bg-fixed-child-clip-2.html bg-fixed-child-clip-ref.html
+skip-if(!asyncPan) == bg-fixed-child-mask.html bg-fixed-child-mask-ref.html
+skip-if(!asyncPan) == bg-fixed-in-opacity.html bg-fixed-in-opacity-ref.html
+# Passing the test below without WebRender would require implementing CSS filters in the Gecko compositor.
+skip-if(!asyncPan) fuzzy-if(gtkWidget,0-1,0-87) fuzzy-if(!gtkWidget,0-1,0-3951) == bg-fixed-in-css-filter.html bg-fixed-in-css-filter-ref.html # bug 1454794 for webrender fuzziness
+skip-if(!asyncPan) == bg-fixed-child-no-culling-1.html bg-fixed-child-no-culling-1-ref.html
+skip-if(!asyncPan) == bg-fixed-child-no-culling-2.html bg-fixed-child-no-culling-2-ref.html
+skip-if(!asyncPan) == bg-fixed-child-no-culling-3.html bg-fixed-child-no-culling-3-ref.html
+fuzzy-if(Android,0-2,0-4000) fuzzy-if(browserIsRemote&&cocoaWidget,0-2,0-179524) fuzzy-if(browserIsRemote&&winWidget,0-1,0-74590) fuzzy-if(gtkWidget&&layersGPUAccelerated,0-1,0-3528) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&/^aarch64-msvc/.test(xulRuntime.XPCOMABI),0-1,0-75900) skip-if(!asyncPan) fuzzy-if(geckoview,0-1,0-74590) == bg-fixed-transformed-image.html bg-fixed-transformed-image-ref.html
+skip-if(!asyncPan) == contain-paint-scrollable-frame-1.html contain-paint-scrollable-frame-1-ref.html
+skip-if(!asyncPan) == element-1.html element-1-ref.html
+pref(layers.force-active,true) skip-if(!asyncPan) == iframe-1.html iframe-1-ref.html
+skip-if(!asyncPan) == nested-1.html nested-1-ref.html
+skip-if(!asyncPan) == nested-2.html nested-2-ref.html
+skip-if(!asyncPan) == position-fixed-1.html position-fixed-1-ref.html
+skip-if(!asyncPan) == position-fixed-2.html position-fixed-2-ref.html
+fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-3120) skip-if(!asyncPan) == position-fixed-body.html position-fixed-body-ref.html
+skip-if(!asyncPan) == position-fixed-cover-1.html position-fixed-cover-1-ref.html
+skip-if(!asyncPan) == position-fixed-cover-2.html position-fixed-cover-2-ref.html
+skip-if(!asyncPan) == position-fixed-cover-3.html position-fixed-cover-3-ref.html
+fuzzy-if(Android,0-15,0-11) fuzzy-if(gtkWidget,20-33,14-32) fuzzy-if(cocoaWidget,9-21,20-44) skip-if(!asyncPan) == position-fixed-transformed-1.html position-fixed-transformed-1-ref.html # Bug 1604338
+skip-if(!asyncPan) == split-layers-1.html split-layers-1-ref.html
+skip-if(!asyncPan) == split-layers-multi-scrolling-1.html split-layers-multi-scrolling-1-ref.html
+fuzzy(0-2,0-240000) skip-if(!asyncPan) == split-opacity-layers-1.html split-opacity-layers-1-ref.html
+skip-if(!asyncPan) fuzzy-if(appleSilicon,0-1,0-8) == sticky-pos-scrollable-1.html sticky-pos-scrollable-1-ref.html
+skip-if(!asyncPan) == sticky-pos-scrollable-2.html sticky-pos-scrollable-2-ref.html
+skip-if(!asyncPan) == sticky-pos-scrollable-3.html sticky-pos-scrollable-3-ref.html
+skip-if(!asyncPan) == sticky-pos-scrollable-4.html sticky-pos-scrollable-4-ref.html
+skip-if(!asyncPan) == sticky-pos-scrollable-5.html sticky-pos-scrollable-5-ref.html
+skip-if(!asyncPan) == sticky-pos-scrollable-6.html sticky-pos-scrollable-6-ref.html
+skip-if(!asyncPan) fuzzy-if(appleSilicon,0-1,0-8) == sticky-pos-scrollable-7.html sticky-pos-scrollable-7-ref.html
+skip-if(!asyncPan) fuzzy(0-2,0-2) fuzzy-if(gtkWidget,0-1,0-4) fuzzy-if(winWidget,0-1,0-51) fuzzy-if(appleSilicon,0-1,0-8) == fixed-pos-scrollable-1.html fixed-pos-scrollable-1-ref.html
+skip-if(!asyncPan) == culling-1.html culling-1-ref.html
+skip-if(!asyncPan) == position-fixed-iframe-1.html position-fixed-iframe-1-ref.html
+skip-if(!asyncPan) == position-fixed-iframe-2.html position-fixed-iframe-2-ref.html
+fuzzy(0-1,0-11300) skip-if(!asyncPan) == position-fixed-in-scroll-container.html position-fixed-in-scroll-container-ref.html
+fuzzy(0-1,0-400) skip-if(!asyncPan) == position-fixed-inside-clip-path.html position-fixed-inside-clip-path-ref.html
+skip-if(!asyncPan) == position-fixed-inside-sticky-1.html position-fixed-inside-sticky-1-ref.html
+skip-if(!asyncPan) == position-fixed-inside-sticky-2.html position-fixed-inside-sticky-2-ref.html
+skip-if(!asyncPan) == position-fixed-inside-sticky-3.html position-fixed-inside-sticky-3-ref.html
+skip-if(!asyncPan) == sticky-inside-fixed-1.html sticky-inside-fixed-1-ref.html
+skip-if(!asyncPan) == sticky-inside-transform-1.html sticky-inside-transform-1-ref.html
+fuzzy(0-1,0-60000) skip-if(!asyncPan) == group-opacity-surface-size-1.html group-opacity-surface-size-1-ref.html
+fuzzy(0-7,0-300) skip-if(!asyncPan) == position-sticky-transformed.html position-sticky-transformed-ref.html
+skip-if(!asyncPan) fuzzy-if(cocoaWidget,0-1,0-396) fuzzy-if(winWidget,0-1,0-396) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
+fuzzy-if(Android,0-43,0-40) fuzzy-if(!Android,0-1,0-34) fuzzy-if(gtkWidget,22-74,20-32) fuzzy-if(cocoaWidget,6-7,18-39) fuzzy-if(swgl&&cocoaWidget&&isDebugBuild,0-7,0-39) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html # Bug 1604338
+fuzzy-if(Android,0-43,0-40) fuzzy-if(gtkWidget,22-74,20-32) fuzzy-if(cocoaWidget,6-7,18-39) fuzzy-if(swgl&&cocoaWidget&&isDebugBuild,0-7,0-39) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html # Bug 1604338
+fuzzy-if(Android,0-43,0-40) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item
+fuzzy-if(Android,0-43,0-40) fuzzy-if(gtkWidget,22-74,20-32) fuzzy-if(cocoaWidget,6-7,18-39) fuzzy-if(swgl&&cocoaWidget&&isDebugBuild,0-7,0-39) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html # Bug 1604338
+fuzzy-if(Android,0-7,0-1680) fuzzy-if(gtkWidget,1-1,2-20) fuzzy-if(cocoaWidget,1-2,10-18) fuzzy-if(swgl&&cocoaWidget&&isDebugBuild,0-2,0-18) skip-if(!asyncPan) == perspective-scrolling-1.html perspective-scrolling-1-ref.html # Bug 1604338
+fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-2.html perspective-scrolling-2-ref.html
+fuzzy-if(Android,0-19,0-10) fuzzy-if(gtkWidget,8-13,12-32) fuzzy-if(cocoaWidget,10-13,20-44) skip-if(!asyncPan) == perspective-scrolling-3.html perspective-scrolling-3-ref.html # Bug 1604338
+fuzzy-if(Android,0-14,0-11) fuzzy-if(gtkWidget,18-30,14-32) fuzzy-if(cocoaWidget,16-20,20-44) skip-if(!asyncPan) == perspective-scrolling-4.html perspective-scrolling-4-ref.html # Bug 1604338
+skip-if(!asyncPan) == perspective-scrolling-5.html perspective-scrolling-5-ref.html
+pref(apz.disable_for_scroll_linked_effects,true) skip-if(!asyncPan) == disable-apz-for-sle-pages.html disable-apz-for-sle-pages-ref.html
+fuzzy-if(browserIsRemote&&d2d,0-1,0-22) skip-if(!asyncPan) fuzzy-if(swgl,0-255,0-11) == background-blend-mode-1.html background-blend-mode-1-ref.html
+skip-if(Android||!asyncPan) != opaque-fractional-displayport-1.html about:blank
+skip-if(Android||!asyncPan) != opaque-fractional-displayport-2.html about:blank
+fuzzy-if(Android,0-19,0-10) fuzzy-if(gtkWidget,12-19,12-32) fuzzy-if(cocoaWidget,17-21,20-44) skip-if(!asyncPan) == fixed-pos-scrolled-clip-1.html fixed-pos-scrolled-clip-1-ref.html # Bug 1604338
+fuzzy-if(Android,0-44,0-136) fuzzy-if(gtkWidget,16-26,26-64) fuzzy-if(cocoaWidget,10-13,38-82) fuzzy-if(winWidget,0-4,0-36) skip-if(!asyncPan) == fixed-pos-scrolled-clip-2.html fixed-pos-scrolled-clip-2-ref.html # Bug 1604338
+fuzzy-if(Android,0-13,0-465) fuzzy-if(gtkWidget,17-28,24-60) fuzzy-if(cocoaWidget,15-19,40-75) skip-if(!asyncPan) == fixed-pos-scrolled-clip-3.html fixed-pos-scrolled-clip-3-ref.html # Bug 1604338
+fuzzy-if(Android,0-13,0-465) fuzzy-if(gtkWidget,17-29,24-60) fuzzy-if(cocoaWidget,15-19,40-75) skip-if(!asyncPan) == fixed-pos-scrolled-clip-4.html fixed-pos-scrolled-clip-4-ref.html # Bug 1604338
+skip-if(!asyncPan) == fixed-pos-scrolled-clip-5.html fixed-pos-scrolled-clip-5-ref.html
+skip-if(!asyncPan) == position-sticky-bug1434250.html position-sticky-bug1434250-ref.html
+fuzzy-if(Android,0-12,0-11) fuzzy-if(gtkWidget,16-25,12-32) fuzzy-if(cocoaWidget,13-16,20-44) skip-if(!asyncPan) == position-sticky-scrolled-clip-1.html position-sticky-scrolled-clip-1-ref.html # Bug 1604338
+fuzzy-if(Android,0-6,0-4) skip == position-sticky-scrolled-clip-2.html position-sticky-scrolled-clip-2-ref.html # bug ?????? - incorrectly applying clip to sticky contents
+fuzzy-if(Android,0-8,0-27) fuzzy-if(cocoaWidget,9-11,20-44) skip-if(!asyncPan) == curtain-effect-1.html curtain-effect-1-ref.html
+fuzzy-if(Android,0-7,0-9) fuzzy-if(gtkWidget,10-15,12-32) fuzzy-if(cocoaWidget,5-9,20-42) skip-if(!asyncPan) == transformed-1.html transformed-1-ref.html # Bug 1604338
+fuzzy-if(Android,2-7,1-12) fuzzy-if(gtkWidget,3-5,12-28) fuzzy-if(cocoaWidget,5-6,18-38) skip-if(!asyncPan) fuzzy-if(swgl&&cocoaWidget&&isDebugBuild,0-6,0-38) == position-sticky-transformed-in-scrollframe-1.html position-sticky-transformed-in-scrollframe-1-ref.html # Bug 1604338
+fuzzy-if(Android,3-3,1-470) fuzzy-if(Android&&swgl&&isDebugBuild&&/^aarch64-gcc3/.test(xulRuntime.XPCOMABI),3-3,457-457) fuzzy-if(gtkWidget,13-20,12-32) fuzzy-if(cocoaWidget,12-16,20-44) skip-if(!asyncPan) == position-sticky-transformed-in-scrollframe-2.html position-sticky-transformed-in-scrollframe-2-ref.html # Bug 1604338
+fuzzy-if(Android,12-13,4-31) fuzzy-if(gtkWidget,16-27,14-32) fuzzy-if(cocoaWidget,13-16,20-44) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-1.html position-sticky-in-transformed-scrollframe-ref.html # Bug 1604338
+fuzzy-if(Android,12-13,4-31) fuzzy-if(gtkWidget,16-27,14-32) fuzzy-if(cocoaWidget,13-16,20-44) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-2.html position-sticky-in-transformed-scrollframe-ref.html # Bug 1604338
+
+skip-if(!asyncPan) == checkerboard-1.html checkerboard-1-ref.html
+skip-if(!asyncPan) == checkerboard-2.html checkerboard-2-ref.html
+skip-if(!asyncPan) == checkerboard-3.html checkerboard-3-ref.html
+skip-if(!asyncPan) == position-sticky-in-checkerboard-land-1.html position-sticky-in-checkerboard-land-1-ref.html
+
+skip-if(!Android) pref(apz.allow_zooming,true) == position-fixed-async-zoom-1.html position-fixed-async-zoom-1-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) == position-fixed-async-zoom-2.html position-fixed-async-zoom-2-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) == position-fixed-async-zoom-3.html position-fixed-async-zoom-3-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) == position-fixed-async-zoom-4.html position-fixed-async-zoom-4-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) == position-sticky-async-zoom-1.html position-sticky-async-zoom-1-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) == position-sticky-async-zoom-2.html position-sticky-async-zoom-2-ref.html
+
+pref(apz.allow_zooming,true) == async-scroll-and-zoom.html async-scroll-and-zoom-ref.html
+
+# on Android we have a different overscroll effect so this test is disabled
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll.html overscroll-ref.html
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-subframe.html overscroll-ref.html
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-fixed.html no-overscroll-ref.html
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-fixed-transform.html overscroll-ref.html
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-fixed-iframe.html overscroll-ref.html
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-fixed-iframe-overscroll.html no-overscroll-ref.html
+# This one needs to be fuzzed due to the fact that squishing a scrollbar
+# thumb on the compositor doesn't preserve its shape exactly.
+skip-if(!asyncPan||Android) fuzzy(0-56,0-33) fuzzy-if(winWidget,0-107,0-17) pref(apz.overscroll.enabled,true) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-scrollbar.html overscroll-scrollbar-ref.html
+skip-if(!asyncPan||Android) pref(apz.overscroll.enabled,false) pref(apz.overscroll.test_async_scroll_offset.enabled,true) == overscroll-disabled.html no-overscroll-ref.html
+
+# for this test, apz.allow_zooming is needed to ensure we take the containerless scrolling codepath that creates
+# an async zoom container (since we are testing a regression in that codepath)
+skip-if(!Android) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.bottom,50) == dynamic-toolbar-fixed-bottom-1.html dynamic-toolbar-fixed-bottom-1-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.bottom,50) == dynamic-toolbar-sticky-bottom-1.html dynamic-toolbar-sticky-bottom-1-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.top,50) == dynamic-toolbar-fixed-top-1.html dynamic-toolbar-fixed-top-1-ref.html
+skip-if(!Android) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.top,50) == dynamic-toolbar-sticky-top-1.html dynamic-toolbar-sticky-top-1-ref.html # bug 1627326 for geckoview&&!webrender
+
+# The next block of tests are based on a single test page which has three
+# sticky items (one sticky to the top, one sticky to the bottom, and one sticky
+# to both top and bottom). It is tested at 6 different scroll offsets, such that
+# a different subset of items is "stuck" at each scroll offset. And each scroll
+# offset has three variants (a, b, and c) where "a" sets the scroll position
+# using main-thread scroll, "b" sets the scroll position using async scroll,
+# and "c" sets the main-thread scroll to the bottom of the page and async-scrolls
+# back up to the desired scroll offset. Therefore the reference page for three
+# variants is always the same.
+defaults fuzzy(0-2,0-120000)
+== dynamic-toolbar-sticky-1a.html dynamic-toolbar-sticky-1-ref.html
+== dynamic-toolbar-sticky-1b.html dynamic-toolbar-sticky-1-ref.html
+== dynamic-toolbar-sticky-1c.html dynamic-toolbar-sticky-1-ref.html
+== dynamic-toolbar-sticky-2a.html dynamic-toolbar-sticky-2-ref.html
+== dynamic-toolbar-sticky-2b.html dynamic-toolbar-sticky-2-ref.html
+== dynamic-toolbar-sticky-2c.html dynamic-toolbar-sticky-2-ref.html
+== dynamic-toolbar-sticky-3a.html dynamic-toolbar-sticky-3-ref.html
+== dynamic-toolbar-sticky-3b.html dynamic-toolbar-sticky-3-ref.html
+== dynamic-toolbar-sticky-3c.html dynamic-toolbar-sticky-3-ref.html
+== dynamic-toolbar-sticky-4a.html dynamic-toolbar-sticky-4-ref.html
+== dynamic-toolbar-sticky-4b.html dynamic-toolbar-sticky-4-ref.html
+== dynamic-toolbar-sticky-4c.html dynamic-toolbar-sticky-4-ref.html
+== dynamic-toolbar-sticky-5a.html dynamic-toolbar-sticky-5-ref.html
+== dynamic-toolbar-sticky-5b.html dynamic-toolbar-sticky-5-ref.html
+== dynamic-toolbar-sticky-5c.html dynamic-toolbar-sticky-5-ref.html
+== dynamic-toolbar-sticky-6a.html dynamic-toolbar-sticky-6-ref.html
+== dynamic-toolbar-sticky-6b.html dynamic-toolbar-sticky-6-ref.html
+== dynamic-toolbar-sticky-6c.html dynamic-toolbar-sticky-6-ref.html
+defaults
+
+# Same as above block of tests, except with a simulated dynamic toolbar
+# at the top. Only the -5 and -6 scroll offsets are impacted, so the
+# reference pages for first 4 scroll offsets are the same as the baseline
+# case.
+defaults skip-if(!geckoview) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.top,50) fuzzy(0-1,0-120000)
+ == dynamic-toolbar-sticky-1a.html dynamic-toolbar-sticky-1-ref.html
+ == dynamic-toolbar-sticky-1b.html dynamic-toolbar-sticky-1-ref.html
+ == dynamic-toolbar-sticky-1c.html dynamic-toolbar-sticky-1-ref.html
+ == dynamic-toolbar-sticky-2a.html dynamic-toolbar-sticky-2-ref.html
+ == dynamic-toolbar-sticky-2b.html dynamic-toolbar-sticky-2-ref.html
+ == dynamic-toolbar-sticky-2c.html dynamic-toolbar-sticky-2-ref.html
+ == dynamic-toolbar-sticky-3a.html dynamic-toolbar-sticky-3-ref.html
+ == dynamic-toolbar-sticky-3b.html dynamic-toolbar-sticky-3-ref.html
+ == dynamic-toolbar-sticky-3c.html dynamic-toolbar-sticky-3-ref.html
+ == dynamic-toolbar-sticky-4a.html dynamic-toolbar-sticky-4-ref.html
+ == dynamic-toolbar-sticky-4b.html dynamic-toolbar-sticky-4-ref.html
+ == dynamic-toolbar-sticky-4c.html dynamic-toolbar-sticky-4-ref.html
+ == dynamic-toolbar-sticky-5a.html dynamic-toolbar-sticky-5-ref-t.html
+ == dynamic-toolbar-sticky-5b.html dynamic-toolbar-sticky-5-ref-t.html
+ == dynamic-toolbar-sticky-5c.html dynamic-toolbar-sticky-5-ref-t.html
+ == dynamic-toolbar-sticky-6a.html dynamic-toolbar-sticky-6-ref-t.html
+== dynamic-toolbar-sticky-6b.html dynamic-toolbar-sticky-6-ref-t.html # bug 1630274 for non-WR
+ == dynamic-toolbar-sticky-6c.html dynamic-toolbar-sticky-6-ref-t.html
+defaults
+
+# Same as above block of tests, except with the dynamic toolbar margin
+# at the bottom of the page. This time the -1 and -2 scroll offsets are
+# impacted.
+defaults skip-if(!geckoview) pref(apz.allow_zooming,true) test-pref(apz.fixed-margin-override.enabled,true) test-pref(apz.fixed-margin-override.bottom,50) fuzzy(0-1,0-120000)
+ == dynamic-toolbar-sticky-1a.html dynamic-toolbar-sticky-1-ref-b.html
+ == dynamic-toolbar-sticky-1b.html dynamic-toolbar-sticky-1-ref-b.html
+== dynamic-toolbar-sticky-1c.html dynamic-toolbar-sticky-1-ref-b.html # bug 1630274 for non-WR
+ == dynamic-toolbar-sticky-2a.html dynamic-toolbar-sticky-2-ref-b.html
+ == dynamic-toolbar-sticky-2b.html dynamic-toolbar-sticky-2-ref-b.html
+ == dynamic-toolbar-sticky-2c.html dynamic-toolbar-sticky-2-ref-b.html
+ == dynamic-toolbar-sticky-3a.html dynamic-toolbar-sticky-3-ref.html
+ == dynamic-toolbar-sticky-3b.html dynamic-toolbar-sticky-3-ref.html
+ == dynamic-toolbar-sticky-3c.html dynamic-toolbar-sticky-3-ref.html
+ == dynamic-toolbar-sticky-4a.html dynamic-toolbar-sticky-4-ref.html
+ == dynamic-toolbar-sticky-4b.html dynamic-toolbar-sticky-4-ref.html
+ == dynamic-toolbar-sticky-4c.html dynamic-toolbar-sticky-4-ref.html
+ == dynamic-toolbar-sticky-5a.html dynamic-toolbar-sticky-5-ref.html
+ == dynamic-toolbar-sticky-5b.html dynamic-toolbar-sticky-5-ref.html
+ == dynamic-toolbar-sticky-5c.html dynamic-toolbar-sticky-5-ref.html
+ == dynamic-toolbar-sticky-6a.html dynamic-toolbar-sticky-6-ref.html
+ == dynamic-toolbar-sticky-6b.html dynamic-toolbar-sticky-6-ref.html
+ == dynamic-toolbar-sticky-6c.html dynamic-toolbar-sticky-6-ref.html
+defaults
diff --git a/layout/reftests/async-scrolling/repeatable-diagonal-gradient.png b/layout/reftests/async-scrolling/repeatable-diagonal-gradient.png
new file mode 100644
index 0000000000..d114e100d3
--- /dev/null
+++ b/layout/reftests/async-scrolling/repeatable-diagonal-gradient.png
Binary files differ
diff --git a/layout/reftests/async-scrolling/split-layers-1-ref.html b/layout/reftests/async-scrolling/split-layers-1-ref.html
new file mode 100644
index 0000000000..2d78cd1738
--- /dev/null
+++ b/layout/reftests/async-scrolling/split-layers-1-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <!-- Test that element content scrolls asynchronously even when content
+ has to be split into separate layers with non-scrolling content in
+ between -->
+ <div style="width:400px; height:500px; overflow:hidden; border:2px solid black">
+ <div style="height:450px"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="left:200px; top:0; height:800px; width:300px; float:left; background:yellow; position:absolute; z-index:1;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/split-layers-1.html b/layout/reftests/async-scrolling/split-layers-1.html
new file mode 100644
index 0000000000..5747986a3c
--- /dev/null
+++ b/layout/reftests/async-scrolling/split-layers-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <!-- Test that element content scrolls asynchronously even when content
+ has to be split into separate layers with non-scrolling content in
+ between -->
+ <div style="width:400px; height:500px; overflow: scroll; scrollbar-width: none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="height:500px"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="left:200px; top:0; height:800px; width:300px; float:left; background:yellow; position:absolute; z-index:1;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
+
diff --git a/layout/reftests/async-scrolling/split-layers-multi-scrolling-1-ref.html b/layout/reftests/async-scrolling/split-layers-multi-scrolling-1-ref.html
new file mode 100644
index 0000000000..bbb8a05290
--- /dev/null
+++ b/layout/reftests/async-scrolling/split-layers-multi-scrolling-1-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <!-- Test that element content scrolls asynchronously even when content
+ has to be split into separate layers with non-scrolling content in
+ between -->
+ <div style="width:400px; height:500px; overflow:hidden; border:2px solid black; margin-top:-50px;">
+ <div style="height:450px"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="left:200px; top:-50px; height:800px; width:300px; float:left; background:yellow; position:absolute; z-index:1;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
+</html>
+
diff --git a/layout/reftests/async-scrolling/split-layers-multi-scrolling-1.html b/layout/reftests/async-scrolling/split-layers-multi-scrolling-1.html
new file mode 100644
index 0000000000..03cd823966
--- /dev/null
+++ b/layout/reftests/async-scrolling/split-layers-multi-scrolling-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50"
+ style="scrollbar-width:none">
+<body style="height:3000px">
+ <!-- Test that element content scrolls asynchronously even when content
+ has to be split into separate layers with non-scrolling content in
+ between -->
+ <div style="width:400px; height:500px; overflow: scroll; scrollbar-width: none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="height:500px"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="left:200px; top:0; height:800px; width:300px; float:left; background:yellow; position:absolute; z-index:1;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
+
diff --git a/layout/reftests/async-scrolling/split-opacity-layers-1-ref.html b/layout/reftests/async-scrolling/split-opacity-layers-1-ref.html
new file mode 100644
index 0000000000..347bfe2547
--- /dev/null
+++ b/layout/reftests/async-scrolling/split-opacity-layers-1-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:500px; overflow:hidden; border:2px solid black">
+ <div style="height:450px"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="opacity:0.5">
+ <div style="left:200px; top:0; height:800px; width:300px; float:left; background:yellow; position:absolute; z-index:1;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
+ </div>
+
diff --git a/layout/reftests/async-scrolling/split-opacity-layers-1.html b/layout/reftests/async-scrolling/split-opacity-layers-1.html
new file mode 100644
index 0000000000..579f515776
--- /dev/null
+++ b/layout/reftests/async-scrolling/split-opacity-layers-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <div style="width:400px; height:500px; overflow:scroll; scrollbar-width: none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div style="height:500px"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="opacity:0.5">
+ <div style="left:200px; top:0; height:800px; width:300px; float:left; background:yellow; position:absolute; z-index:1;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
+ </div>
+
diff --git a/layout/reftests/async-scrolling/sticky-inside-fixed-1-ref.html b/layout/reftests/async-scrolling/sticky-inside-fixed-1-ref.html
new file mode 100644
index 0000000000..6e9883f591
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-inside-fixed-1-ref.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Testcase for Bug 1501342</title>
+ <style>
+ .panel {
+ height:100%;
+ overflow:hidden;
+ position:fixed;
+ right:0;
+ }
+ .scrollable {
+ height:100%;
+ overflow-y:hidden;
+ }
+ .sticky {
+ position:sticky;
+ top:0;
+ height: 50px;
+ width: 100px;
+ background: red;
+ }
+ .content {
+ margin-top: -50px;
+ height:2000px;
+ width:200px;
+ background:green;
+ }
+ </style>
+</head>
+<body>
+ <div class="panel">
+ <div class="scrollable">
+ <div class="sticky"></div>
+ <div class="content"></div>
+ </div>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/layout/reftests/async-scrolling/sticky-inside-fixed-1.html b/layout/reftests/async-scrolling/sticky-inside-fixed-1.html
new file mode 100644
index 0000000000..ba7da94702
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-inside-fixed-1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html reftest-async-scroll>
+<head>
+ <title>Testcase for Bug 1501342</title>
+ <style>
+ .panel {
+ height:100%;
+ overflow:hidden;
+ position:fixed;
+ right:0;
+ }
+ .scrollable {
+ height:100%;
+ overflow-y: scroll;
+ scrollbar-width: none;
+ }
+ .sticky {
+ position:sticky;
+ top:0;
+ height: 50px;
+ width: 100px;
+ background: red;
+ }
+ .content {
+ height:2000px;
+ width:200px;
+ background:green;
+ }
+ </style>
+</head>
+<body>
+ <div class="panel">
+ <div class="scrollable"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+ <div class="sticky"></div>
+ <div class="content"></div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/async-scrolling/sticky-inside-transform-1-ref.html b/layout/reftests/async-scrolling/sticky-inside-transform-1-ref.html
new file mode 100644
index 0000000000..c778de137a
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-inside-transform-1-ref.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<meta charset="utf-8" />
+<style>
+html, body { margin: 0 }
+
+#scroll {
+ overflow-y: auto;
+ scrollbar-width: none;
+ height: 100vh;
+ background: green;
+}
+#transform {
+ transform: translateX(100%) rotate(90deg);
+ height: 600px;
+ position: relative;
+ top: -300px;
+ transform-origin: 0% 0%;
+ background: #ff0;
+}
+#sticky {
+ position: relative;
+ top: 300px;
+ background: #0ff;
+ height: 100px;
+}
+</style>
+<div id="scroll">
+ <div id="transform">
+ <div id="sticky"></div>
+ </div>
+ <div id="content" style="height: 2000px;"></div>
+</div>
+</html>
diff --git a/layout/reftests/async-scrolling/sticky-inside-transform-1.html b/layout/reftests/async-scrolling/sticky-inside-transform-1.html
new file mode 100644
index 0000000000..a1d55a3211
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-inside-transform-1.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<html reftest-async-scroll>
+<meta charset="utf-8" />
+<style>
+html, body { margin: 0 }
+
+#scroll {
+ overflow-y: auto;
+ scrollbar-width: none;
+ height: 100vh;
+ background: green;
+}
+#transform {
+ transform: translateX(100%) rotate(90deg);
+ height: 600px;
+ transform-origin: 0% 0%;
+ background: #ff0;
+}
+#sticky {
+ position: sticky;
+ top: 0;
+ background: #0ff;
+ height: 100px;
+}
+</style>
+<div id="scroll"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="300">
+ <div id="transform">
+ <div id="sticky"></div>
+ </div>
+ <div id="content" style="height: 2000px"></div>
+</div>
+</html>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-1-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-1-ref.html
new file mode 100644
index 0000000000..2522f82e2e
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:300px; overflow:hidden; border:2px solid black">
+ <div style="height:200px; width:200px; float:left; background:white"></div>
+ <div style="left:200px; top:0; height:300px; width:200px; float:right; background:yellow;"></div>
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-1.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-1.html
new file mode 100644
index 0000000000..3043e3a913
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <div style="width:400px; height:300px; overflow:scroll; scrollbar-width:none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+ <!-- In this test the position:sticky element gets its own layer, and also has scrollable metrics
+ because it shares the same animated geometry root as the other elements. This tests that
+ layers with both sticky info and scroll info are transformed correctly in the face of an async
+ scroll transform. -->
+ <div style="height:100px; width:200px; float:left; background:purple"></div>
+ <div style="left:200px; top:0; height:300px; width:200px; float:left; background:yellow; position:sticky; z-index:1;"></div>
+ <div style="height:300px; width:200px; float:left; background:purple; position:relative; z-index:2;"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-2-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-2-ref.html
new file mode 100644
index 0000000000..da90b19984
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-2-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<style>
+body {
+ margin: 0;
+ height: 4000px;
+ overflow: hidden;
+}
+div {
+ background: blue;
+ width: 200px;
+ height: 200px;
+ margin-top: 300px;
+ position: sticky;
+ bottom: 100px;
+}
+</style>
+<div></div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-2.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-2.html
new file mode 100644
index 0000000000..73ae7c75d3
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+<style>
+html {
+ scrollbar-width: none;
+}
+body {
+ margin: 0;
+ height: 4000px;
+}
+div {
+ background: blue;
+ width: 200px;
+ height: 200px;
+ margin-top: 400px;
+ position: sticky;
+ bottom: 100px;
+}
+</style>
+<div></div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-3-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-3-ref.html
new file mode 100644
index 0000000000..fab9f954ba
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-3-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <style>
+ #header {
+ position: fixed;
+ top: 0;
+ }
+ #header > div {
+ border: solid blue 2px;
+ height: 100px;
+ width: 100px;
+ }
+ </style>
+ <div id="section">
+ <div id="header">
+ <div></div>
+ </div>
+ </div>
+</html> \ No newline at end of file
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-3.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-3.html
new file mode 100644
index 0000000000..5581f8a0ac
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-3.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ #section {
+ padding-top: 1px;
+ }
+ #header {
+ position: sticky;
+ top: 0;
+ }
+ #header > div {
+ margin-top: -50px;
+ border: solid blue 2px;
+ height: 100px;
+ width: 100px;
+ }
+ #spacer {
+ height: 1500px;
+ }
+ </style>
+ <div id="section">
+ <div id="header">
+ <div></div>
+ </div>
+ <div id="spacer"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-4-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-4-ref.html
new file mode 100644
index 0000000000..c8e0e220bd
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-4-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:300px; overflow:hidden; border:2px solid black">
+ <div style="height: 150px"></div>
+ <div style="width: 100px; height: 100px; background-color: green"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-4.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-4.html
new file mode 100644
index 0000000000..291c5c40fa
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-4.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <div style="width:400px; height:300px; overflow:scroll; scrollbar-width:none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+ <!-- In this test the position:sticky element has already been adjusted by
+ the main thread paint, and the async scroll causes a reduction in that
+ adjustment. -->
+ <div style="height: 1000px"></div>
+ <div style="position:sticky; width: 100px; height: 100px; bottom: 50px; background-color: green"></div>
+ <div style="height: 1000px"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-5-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-5-ref.html
new file mode 100644
index 0000000000..c8e0e220bd
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-5-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:300px; overflow:hidden; border:2px solid black">
+ <div style="height: 150px"></div>
+ <div style="width: 100px; height: 100px; background-color: green"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-5.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-5.html
new file mode 100644
index 0000000000..61f4e4c968
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-5.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <div style="width:400px; height:300px; overflow:scroll; scrollbar-width:none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="150">
+ <!-- In this test the position:sticky element has already been adjusted by
+ the main thread paint, and then clamped by the bounding container. The
+ async scroll causes a reduction in that adjustment, but by less than
+ the amount of the scroll (because of the clamping). -->
+ <div style="height: 500px; margin-top: 250px; margin-bottom: 250px">
+ <div style="width: 100px; height: 300px"></div>
+ <div style="position:sticky; width: 100px; height: 100px; bottom: 50px; background-color: green"></div>
+ </div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-6-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-6-ref.html
new file mode 100644
index 0000000000..f8797f108f
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-6-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+ <div style="width:400px; height:300px; overflow:hidden; border:2px solid black">
+ <div style="height: 151px"></div>
+ <div style="width: 100px; height: 100px; background-color: green"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-6.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-6.html
new file mode 100644
index 0000000000..5db3fac2cd
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-6.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html reftest-async-scroll>
+<body>
+ <div style="width:400px; height:300px; overflow:scroll; scrollbar-width:none; border:2px solid black"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="300">
+ <!-- In this test the position:sticky element is over-constrained with the
+ top-positioning taking priority over the bottom-positioning. -->
+ <div style="height: 300px"></div>
+ <div style="position:sticky; width: 100px; height: 100px; top: 151px; bottom: 50px; background-color: green"></div>
+ <div style="height: 1000px"></div>
+ </div>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-7-ref.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-7-ref.html
new file mode 100644
index 0000000000..92105b51f2
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-7-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <style>
+ #header {
+ position: fixed;
+ top: 0;
+ left: 9px;
+ }
+ #header > div {
+ border-radius: 10px;
+ overflow:hidden;
+ height: 100px;
+ width: 100px;
+ }
+ #inner {
+ width: 200px;
+ height: 200px;
+ background-color:green;
+ }
+ </style>
+ <div id="section">
+ <div id="header">
+ <div>
+ <div id="inner"></div>
+ </div>
+ </div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/sticky-pos-scrollable-7.html b/layout/reftests/async-scrolling/sticky-pos-scrollable-7.html
new file mode 100644
index 0000000000..03c8a23da7
--- /dev/null
+++ b/layout/reftests/async-scrolling/sticky-pos-scrollable-7.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="100">
+ <style>
+ html {
+ scrollbar-width: none;
+ }
+ #section {
+ padding-top: 1px;
+ transform: translateX(1px);
+ }
+ #header {
+ position: sticky;
+ top: 0;
+ }
+ #header > div {
+ margin-top: -50px;
+ border-radius: 10px;
+ overflow:hidden;
+ height: 100px;
+ width: 100px;
+ }
+ #spacer {
+ height: 1500px;
+ }
+ #inner {
+ width: 200px;
+ height: 200px;
+ background-color:green;
+ }
+ </style>
+ <div id="section">
+ <div id="header">
+ <div>
+ <div id="inner"></div>
+ </div>
+ </div>
+ <div id="spacer"></div>
+ </div>
+</html>
diff --git a/layout/reftests/async-scrolling/transformed-1-ref.html b/layout/reftests/async-scrolling/transformed-1-ref.html
new file mode 100644
index 0000000000..2e04e6b88e
--- /dev/null
+++ b/layout/reftests/async-scrolling/transformed-1-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <head><title>Async scrolling with transforms</title></head>
+ <body style="height: 2000px" onload="window.scrollTo(0,20); document.documentElement.classList.remove('reftest-wait')">
+ <div style="transform: rotate(90deg); transform-origin: bottom left">Some vertical text</div>
+ </body>
+</html>
diff --git a/layout/reftests/async-scrolling/transformed-1.html b/layout/reftests/async-scrolling/transformed-1.html
new file mode 100644
index 0000000000..1aa2f10684
--- /dev/null
+++ b/layout/reftests/async-scrolling/transformed-1.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="20">
+ <head><title>Async scrolling with transforms</title></head>
+ <body style="height: 2000px">
+ <div style="transform: rotate(90deg); transform-origin: bottom left">Some vertical text</div>
+ </body>
+</html>