<!DOCTYPE html>
<head>
<script src="../resources/gc.js"></script>
<body>
<pre id="log">This tests removing the root node of IntersectionObserver. The root node should be eligible for GC.

</pre>
<script>

function createRoot(rootId)
{
    const container = document.createElement('div');
    container.innerHTML = `<div id="${rootId}" class="root" style="position:absolute"><div class="target" style="width: 100px; height: 100px; background-color: green"></div></div>`;
    const root = container.getElementsByClassName('root')[0];
    root.remove();
    return root;
}

let initialNodeCount = 0;
window.onload = () => {
    if (!window.testRunner || !window.internals) {
        log.textContent += 'FAIL - This test requires internals';
        return;
    }
    if (internals.numberOfIntersectionObservers(document)) {
        log.textContent += 'FAIL - Initial intersection observer count is not zero';
        return;
    }
    initialNodeCount = internals.referencingNodeCount(document);
    testRunner.dumpAsText();
    testRunner.waitUntilDone();
    setTimeout(() => testRunner.notifyDone(), 5000);
    runTest(1);
}

const totalTestCount = 20;
function runTest(testNumber) {
    log.textContent += `Test ${testNumber}: `;
    const rootId = 'root-' + testNumber;
    let root = createRoot(rootId);
    root.alive = true;
    document.body.appendChild(root);

    let observer = new IntersectionObserver(() => { }, { root });
    let target = root.getElementsByClassName('target')[0];
    if (observer.root != root)
        return testFailed(testNumber, 'observer.root != root after construction');
    observer.observe(target);

    root.remove();
    root = null;
    target = null;
    // add a timeout between requestAnimationFrame calls to allow opportunistic node deletion to occur
    setTimeout(() => { requestAnimationFrame(function () {
        observer.takeRecords();
        gc();

        if (!observer.root)
            return testFailed(testNumber, 'observer.root is null');
        if (observer.root.id != rootId)
            return testFailed(testNumber, `observer.root.id (${observer.root.id}) != rootId (${rootId}) after running rAF and GC`);
        if (!observer.root.alive)
            return testFailed(testNumber, 'observer.alive is false');

        observer = null;
        gc();

        log.textContent += 'PASS\n';

        if (testNumber < totalTestCount)
            setTimeout(() => runTest(testNumber + 1), 0);
        else
            setTimeout(() => finish(testNumber), 0);
    });
    }, 5);
}

function testFailed(testNumber, error)
{
    log.textContent += `FAIL: ${error}\n`;
    finish(testNumber);
}

function finish(finishedTestCount)
{
    log.textContent += 'Node count: ';
    log.textContent += (internals.referencingNodeCount(document) < initialNodeCount + 2 * finishedTestCount * 0.8) ? 'PASS' : 'FAIL - Less than 20% of the root nodes were collected';
    log.textContent += '\n';
    log.textContent += 'Intersection observer count: ';
    log.textContent += (internals.numberOfIntersectionObservers(document) < finishedTestCount * 0.8) ? 'PASS' : 'FAIL - Less than 20% of the intersection observers were collected';
    log.textContent += '\n';
    testRunner.notifyDone();
}

</script>
</body>
</html>
