<body>
<p>Test that HTMLSelectElement DOM is in a consistent state when handling mutation events.</p>
<form>
<select multiple size=5><option>1</option><option>2</option></select>
</form>
<div id=res></div>
<script>
if (window.testRunner)
    testRunner.dumpAsText();

var select = document.forms[0].elements[0];
var res = document.getElementById("res");
var hadFailure = false;

function logError(message)
{
    res.innerHTML += message + "<br>";
    hadFailure = true;
}

// { test number, expected length, item to check, expected result }
var testInfo;

function checkSelect(evt)
{
    // Force layout to verify that DOM is in a consistent state.
    document.body.offsetTop;

    if (!testInfo[0])
        return;

    if (select.length != testInfo[1])
        logError("Test " + testInfo[0] + ". " + evt.type + ": Incorrect length. Was " + select.length + ", expected " + testInfo[1] + ".");

    if (testInfo[3]) {
        if (select.item(testInfo[2]).value != testInfo[3])
            logError("Test " + testInfo[0] + ". " + evt.type + ": Incorrect item " + testInfo[2] + " value. Was " + select.item(testInfo[2]).value + ", expected " + testInfo[3] + ".");
    } else {
        if (select.item(testInfo[2]))
            logError("Test " + testInfo[0] + ". " + evt.type + ": Item " + testInfo[2] + " exists when it should not.");
    }
}

function onNodeRemoved()
{
    // Force layout to verify that DOM is in a consistent state.
    document.body.offsetTop;

    if (select.length != 2) {
        alert("FAIL: Incorrect length after removing an option.");
        hadFailure = true;
    }

    if (select.item(2)) {
        alert("FAIL: A removed option is still present when handling a DOMNodeRemoved event.");
        hadFailure = true;
    }
}

select.addEventListener("DOMNodeInserted", checkSelect, true);
select.addEventListener("DOMNodeInsertedIntoDocument", checkSelect, true);
select.addEventListener("DOMSubtreeModified", checkSelect, true);
select.addEventListener("DOMSubtreeModified", checkSelect, true);

testInfo = [1, 3, 2, "3"];
select.appendChild(new Option("3", "3", false, false));
checkSelect();

testInfo = [2, 2, 2, undefined];
select.removeChild(select.lastChild);
checkSelect();

testInfo = []; // A DOMSubtreeModified event may be dispatched between removal and addition, skip checks.
select.replaceChild(new Option("new", "new", false, false), select.lastChild);
testInfo = [3, 2, 1, "new"];
checkSelect();

testInfo = [4, 3, 0, "0"];
select.add(new Option("0", "0", false, false), select.firstChild);
testInfo = [4, 3, 0, "0"];
checkSelect();

testInfo = [5, 2, 0, "1"];
select.remove(0);
testInfo = [5, 2, 0, "1"];
checkSelect();

testInfo = [6, 3, 0, "-1"];
select.insertBefore(new Option("-1", "-1", false, false), select.firstChild);
testInfo = [6, 3, 0, "-1"];
checkSelect();

testInfo = [7, 3, 0, "-"];
select.firstChild.value = "-";
select.firstChild.text = "-";
testInfo = [7, 3, 0, "-"];
checkSelect();

testInfo = []; // Multiple DOMSubtreeModified event may be dispatched, skip check.
select.innerHTML = "<optgroup><option>1</option><option>2</option></optgroup>";
testInfo = [8, 2, 0, 1];
checkSelect();

var optgroup = select.firstChild;

testInfo = [9, 3, 2, "3"];
optgroup.appendChild(new Option("3", "3", false, false));
checkSelect();

testInfo = [10, 2, 2, undefined];
optgroup.removeChild(optgroup.lastChild);
checkSelect();

testInfo = []; // A DOMSubtreeModified event may be dispatched between removal and addition, skip checks.
optgroup.replaceChild(new Option("new", "new", false, false), optgroup.lastChild);
testInfo = [11, 2, 1, "new"];
checkSelect();

/* WebKit cannot add options right into a group via HTMLSelectElement.add().
   See <https://bugs.webkit.org/show_bug.cgi?id=24606>.
testInfo = [12, 3, 0, "0"];
select.add(new Option("0", "0", false, false), optgroup.firstChild);
testInfo = [12, 3, 0, "0"];
checkSelect();

testInfo = [13, 2, 0, "1"];
select.remove(0);
checkSelect();
*/

testInfo = [14, 3, 0, "-1"];
optgroup.insertBefore(new Option("-1", "-1", false, false), optgroup.firstChild);
checkSelect();

testInfo = [15, 3, 0, "-"];
optgroup.firstChild.value = "-";
optgroup.firstChild.text = "-";
checkSelect();

testInfo = [16, 0, 0, undefined];
optgroup.innerHTML = "";
checkSelect();

if (!hadFailure)
    res.innerHTML = "SUCCESS";
</script>
