Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<!-- A position:sticky <th> lives in an overflow-x scroll container, inside a
transform, inside an outer vertical scroll container (#radix) that starts
async-inactive. Growing #spacer makes #radix async-active during a partial
display list update without revisiting the retained sticky items, so their
cached scroll-tree node depths must not go stale. -->
<html class="test-wait">
<head>
<meta charset="utf-8">
<style>
body { margin: 0; font: 13px/1.4 sans-serif; }
* { scrollbar-width: none; }
#outer { height: 500px; overflow-y: auto; }
#outer-content { height: 3000px; padding: 10px; }
#radix {
height: 460px;
overflow-y: auto;
overflow-x: hidden;
border: 2px solid #333;
width: 400px;
}
#overflow-x-auto { overflow-x: auto; }
#spacer { height: 0; }
table { width: 1000px; table-layout: fixed; border-collapse: collapse; }
thead { will-change: transform; }
th, td { box-sizing: border-box; height: 40px; border: 1px solid #ccc; padding: 0 4px; }
th { position: sticky; top: 0; background: #4a90d9; color: white; }
</style>
</head>
<body>
<div id="outer">
<div id="outer-content">
<div id="radix">
<div id="overflow-x-auto">
<div style="transform: translate(0px, 0px)">
<table>
<thead>
<tr><th>A</th><th>B</th><th>C</th><th>D</th></tr>
</thead>
<tbody>
<tr><td>0</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>1</td><td>1</td><td>1</td><td>1</td></tr>
<tr><td>2</td><td>2</td><td>2</td><td>2</td></tr>
<tr><td>3</td><td>3</td><td>3</td><td>3</td></tr>
<tr><td>4</td><td>4</td><td>4</td><td>4</td></tr>
<tr><td>5</td><td>5</td><td>5</td><td>5</td></tr>
<tr><td>6</td><td>6</td><td>6</td><td>6</td></tr>
<tr><td>7</td><td>7</td><td>7</td><td>7</td></tr>
<tr><td>8</td><td>8</td><td>8</td><td>8</td></tr>
<tr><td>9</td><td>9</td><td>9</td><td>9</td></tr>
</tbody>
</table>
</div>
</div>
<div id="spacer"></div>
</div>
</div>
</div>
<script>
function raf() { return new Promise(r => requestAnimationFrame(r)); }
onload = async () => {
// Wait for the first paint so #radix is built async-inactive and its
// descendants' scroll-tree nodes are cached.
await raf();
await raf();
// Activate #radix without touching the retained sticky items.
document.getElementById("spacer").style.height = "400px";
// Let the partial-update paint that would crash happen.
await raf();
await raf();
document.documentElement.classList.remove("test-wait");
};
</script>
</body>
</html>