/*===
basic
foo
bar
proto
0 foo
1 bar
===*/

print('basic');

function basicTest() {
    var proto = { proto: 'prototype' };
    var obj;
    var keys;
    var i;

    obj = Object.create(proto);
    obj.foo = 1;
    obj.bar = 2;

    Object.defineProperties(proto, {
        proto_nonenum: { value: 1, writable: true, enumerable: false, configurable: true }
    });

    Object.defineProperties(obj, {
        nonenum: { value: 1, writable: true, enumerable: false, configurable: true }
    });


    // Here we make an assumption on enumeration order.
    // Enumeration includes prototype 'proto' property too.

    for (i in obj) {
        print(i);
    }

    // Object.keys() only includes own enumerable properties.

    keys = Object.keys(obj);
    for (i = 0; i < keys.length; i++) {
        print(i, keys[i]);
    }
}

try {
    basicTest();
} catch (e) {
    print(e);
}

/*===
coercion
TypeError
TypeError
TypeError
TypeError
TypeError
TypeError
TypeError
object 2
object 2
===*/

print('coercion');

function coercionTest() {
    function test(o, is_noargs) {
        var t;

        try {
            if (is_noargs) {
                t = Object.keys();
            } else {
                t = Object.keys(o);
            }
            print(typeof t, t.length);
        } catch (e) {
            print(e.name);
        }
    }

    test(undefined, true);
    test(undefined);
    test(null);
    test(true);
    test(false);
    test(123);
    test('foo');
    test([1,2]);
    test({ foo: 1, bar: 2 });
}

try {
    coercionTest();
} catch (e) {
    print(e);
}

