<!DOCTYPE html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true ] -->
<html>
<head>
<style>
    .viewport {
        border: 1px solid #000;
        height: 200px;
        width: 300px;
        overflow: auto;
    }

    .grid {
        position: relative;
        background-color: red;
        display: inline-grid;
        grid-template-columns: repeat(2, 120px);
        grid-template-rows: repeat(25px);
        grid-gap: 1px;
    }

    .grid > div {
        background-color: white;
        box-sizing: border-box;
        height: 25px;
    }
</style>
<script src="../../resources/js-test-pre.js"></script>
<script>
    jsTestIsAsync = true;
        
    window.addEventListener('load', () => {
        let viewport = document.querySelector('.viewport');
        let canvas = document.querySelector('.canvas');
        let grid = document.querySelector('.grid');
        const gridGap = 1;
        const rowHeight = 25;
        const rowHeightWithGridGap = rowHeight + gridGap;

        let data = Array(500).fill(null).map((i, index) => [
            index,
            index + 1
        ]);

        canvas.style = `
          height: ${(rowHeight + gridGap) * 500}px; 
          width: ${(120 + gridGap) * 10}px
        `;

        viewport.addEventListener('scroll', getVisibleRows);

        function getVisibleRows()
        {
          let { first, last } = getVisibleRowsRange();
          let top = first * rowHeightWithGridGap;
          redrawRows(data.slice(first, last), top);
        }

        function getVisibleRowsRange()
        {
          const { offsetHeight, scrollTop } = viewport;
          const firstVisibleRow = Math.max(Math.floor((scrollTop + gridGap) / rowHeightWithGridGap), 0);
          const lastVisibleRow = Math.min(Math.floor((scrollTop + offsetHeight) / rowHeightWithGridGap), data.length - 1);
          return { first: firstVisibleRow, last: lastVisibleRow + 1 };
        }

        function redrawRows(rows, top)
        {
          clearExistingRows();
          grid.style.top = `${top}px`;
          drawRows(rows);
        }

        function clearExistingRows()
        {
          while (grid.firstChild)
            grid.removeChild(grid.firstChild);
        }

        function drawRows(rows)
        {
          rows.forEach(row => {
            row.forEach((cell, i) => {
              let el = document.createElement('div');
              el.style = i < 1 ? 'position: sticky' : '';
              el.textContent = cell;
              grid.appendChild(el);
            });
          });
        }

        getVisibleRows();
        
        requestAnimationFrame(() => {
            viewport.scrollTo(0, 200);

            requestAnimationFrame(() => {
                viewport.scrollTo(0, 400);
                shouldBeTrue("window.internals?.scrollingStateTreeAsText().indexOf('unparented node count') == -1");
                finishJSTest();
            })
        })
    }, false);
</script>
</head>
<body>
    <div class="viewport">
        <div class="canvas">
            <div class="grid"></div>
        </div>
    </div>
<div id="console"></div>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>