<html>
<head></head>
<body>
<div id="description"></div>
<input type="file" id="fileInput">
<div id="console"></div>
<script>
if (window.testRunner) {
    testRunner.dumpAsText();
    testRunner.waitUntilDone();
}

var console = document.getElementById("console");

var tests = [];

function equal(actual, expected)
{
    if (typeof actual !== typeof expected)
        return false;
    if (actual === expected)
        return true;
    if ((actual instanceof Date) || (expected instanceof Date)) {
        if ((actual instanceof Date) && (expected instanceof Date))
            return (expected instanceof Date) && actual.getTime() == expected.getTime();
        return false;
    }
    if (Array.isArray(actual) || Array.isArray(expected)) {
        if (!Array.isArray(actual) || !Array.isArray(expected))
            return false;
        if (actual.length != expected.length)
            return false;
        for (var i = 0; i < actual.length; i++) {
            if ((i in actual) ^ (i in expected))
                return false;
            if (!equal(actual[i], expected[i]))
                return false;
        }
        return true;
    }
    if (actual.constructor !== expected.constructor)
        return false;
    if ("object" != typeof actual)
        return false;
    var keys = Object.keys(actual);
    if (!equal(keys, Object.keys(expected)))
        return false;
    for (var i = 0; i < keys.length; i++) {
        if (!equal(actual[keys[i]], expected[keys[i]]))
            return false;
    }
    return true;
}

function safeToString(o) {
    if (o instanceof Date)
        return o.toISOString();
    if (typeof o !== "object" || !o)
        return o;
    try {
        return o.toString();
    } catch (e) {
        return Object.prototype.toString.call(o) + "(default toString threw "+e+")";
    }
}

function shouldBe(actual, expected)
{
    var actualValue = eval(actual);
    var expectedValue = eval(expected);
    if (equal(actualValue, expectedValue))
        console.innerHTML += "PASS: " + actual + " is " + safeToString(expectedValue) + " of type " + typeof actualValue + "<br>";
    else
        console.innerHTML += "FAIL: " + actual + " is " + actualValue + " should be " + expectedValue + " of type " + typeof expectedValue + "<br>";
}
var i = 0;
window.onmessage = function(evt) {
    if (safeToString(frames[0].tests[i].eventData) == 'done') {
        if (window.testRunner)
            testRunner.notifyDone();
        return;
    }

    shouldBe("(frames[0].tests["+i+"]).eventData instanceof (frames[0])."+tests[i].constructor, "true");
    shouldBe("(frames[0].tests["+i+"]).event.data instanceof (frames[0])."+tests[i].constructor, "true");
    i++;
}

function tryPostMessage(message, constructor) {
    try {
        var value = eval(message);
        frames[0].postMessage(value, "*");
        tests.push({constructor: constructor});
    } catch(e) {
        console.innerHTML += "FAIL: 'postMessage("+message+")' should not throw but threw " + e + "<br>";
    }
}

document.getElementById("description").innerHTML = "Tests that we clone object hierarchies";

function startTest() {
    tryPostMessage('({})', "Object");
    tryPostMessage('[]', "Array");
    tryPostMessage('new Date', "Date");
    var fileInput = document.getElementById("fileInput");
    var fileRect = fileInput.getClientRects()[0];
    var targetX = fileRect.left + fileRect.width / 2;
    var targetY = fileRect.top + fileRect.height / 2;
    if (window.eventSender) {
        eventSender.beginDragWithFiles(['get-file-upload.html']);
        eventSender.mouseMoveTo(targetX, targetY);
        eventSender.mouseUp();
        tryPostMessage('fileInput.files[0]', "File");
        tryPostMessage('fileInput.files', "FileList");
    }
    tryPostMessage('"done"');
}
</script>
<iframe src="resources/window-postmessage-clone-frames-frame.html" onload="startTest()"></iframe>
</body>
</html>
