<p>
This page tests cached access to getters and setters. If the test passes,
you'll see a series of PASS messages below.
</p>

<pre id="console"></pre>

<script>
(function() {
    if (window.testRunner)
        testRunner.dumpAsText();

    function log(s)
    {
        if (this.document)
            document.getElementById("console").appendChild(document.createTextNode(s + "\n"));
        else
            print(s + "\n");
    }
    
    function shouldBe(a, aDescription, b)
    {
        if (a === b) {
            log("PASS: " + aDescription + " should be " + b + " and is.");
        } else {
            log("FAIL: " + aDescription + " should be " + b + " but instead is " + a + ".");
        }
    }
    
    (function() {
        var o = {
            x_ : 0,
            y_ : 0,

            get x() { return this.x_; },
            set x(x) { this.x_ = x; },

            __proto__ : {
                get y() { return this.y_; },
                set y(y) { this.y_ = y; }
            }
        };

        for (var i = 0; i < 3; ++i) {
            o.x = i;
            shouldBe(o.x, "o.x", i);
        }

        for (var i = 0; i < 3; ++i) {
            o.y = i;
            shouldBe(o.y, "o.y", i);
        }
    })();

    function testGetter(o) {
        var result;
        for (var i = 0; i < 10; i++)
            result = o.getter;
        return result;
    }
    function testProtoGetter(o) {
        var result;
        for (var i = 0; i < 10; i++)
            result = o.getter;
        return result;
    }
    function testProtoChainGetter(o) {
        var result;
        for (var i = 0; i < 10; i++)
            result = o.getter;
        return result;
    }
    shouldBe(testGetter({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0}), 
            "testGetter({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0})", 10);
    shouldBe(testGetter({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty: 0}), 
            "testGetter({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty: 0})", 10);
    shouldBe(testGetter({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty2: 0}), 
            "testGetter({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty2: 0})", 10);
    shouldBe(testProtoGetter({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}, count: 0}), 
            "testProtoGetter({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}, count: 0})", 10);
    shouldBe(testProtoGetter({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}, count: 0, newProperty: 0}), 
            "testProtoGetter({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}, count: 0, newProperty: 0})", 10);
    shouldBe(testProtoGetter({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}, count: 0, newProperty2: 0}), 
            "testProtoGetter({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}, count: 0, newProperty2: 0})", 10);
    shouldBe(testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}}, count: 0}), 
            "testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}}, count: 0})", 10);
    shouldBe(testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}}, count: 0, newProperty: 0}), 
            "testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}}, count: 0, newProperty: 0})", 10);
    shouldBe(testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}}, count: 0, newProperty2: 0}),
            "testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }}}, count: 0, newProperty2: 0})", 10);

    function testGetterBigObject(o) {
        var result;
        for (var i = 0; i < 10; i++)
            result = o.getter;
        return result;
    }
    function testProtoGetterBigObject(o) {
        var result;
        for (var i = 0; i < 10; i++)
            result = o.getter;
        return result;
    }
    function testProtoChainGetterBigObject(o) {
        var result;
        for (var i = 0; i < 10; i++)
            result = o.getter;
        return result;
    }
    shouldBe(testGetterBigObject({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}), 
            "testGetterBigObject({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9})", 10);
    shouldBe(testGetterBigObject({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty: 0, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}), 
            "testGetterBigObject({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty: 0, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9})", 10);
    shouldBe(testGetterBigObject({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty2: 0, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}), 
            "testGetterBigObject({__proto__: {count: 'FAIL'}, get getter(){ return ++this.count; }, count: 0, newProperty2: 0, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9})", 10);
    shouldBe(testProtoGetterBigObject({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}, count: 0}), 
            "testProtoGetterBigObject({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}, count: 0})", 10);
    shouldBe(testProtoGetterBigObject({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}, count: 0, newProperty: 0}), 
            "testProtoGetterBigObject({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}, count: 0, newProperty: 0})", 10);
    shouldBe(testProtoGetterBigObject({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}, count: 0, newProperty2: 0}), 
            "testProtoGetterBigObject({__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}, count: 0, newProperty2: 0})", 10);
    shouldBe(testProtoChainGetterBigObject({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}}, count: 0}), 
            "testProtoChainGetterBigObject({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}}, count: 0})", 10);
    shouldBe(testProtoChainGetterBigObject({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}}, count: 0, newProperty: 0}), 
            "testProtoChainGetterBigObject({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}}, count: 0, newProperty: 0})", 10);
    shouldBe(testProtoChainGetterBigObject({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}}, count: 0, newProperty2: 0}),
            "testProtoChainGetterBigObject({__proto__: {__proto__: {count: 'FAIL', get getter(){ return ++this.count; }, a:1, b:2, c:3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}}, count: 0, newProperty2: 0})", 10);

    (function() {
        var o = {
            x : 1,
            y : 1
        };
        
        function getX(o)
        {
            return o.x;
        }
        
        function setX(o, x)
        {
            o.x = x;
        }
        
        getX(o);
        getX(o);
        
        setX(o, 2);
        setX(o, 2);

        o.__defineGetter__("x", function() { return 3; });
        o.__defineSetter__("x", function(x) { });
        
        shouldBe(getX(o), "getX(o)", 3);
        setX(o, 2);
        shouldBe(getX(o), "getX(o)", 3);
    })();
})();
</script>
