
/*===
bar
bar
bar
SyntaxError
===*/

print({foo:'bar'}.foo);    // key without quotes
print({"foo":'bar'}.foo);  // key with quotes
print({foo:'bar',}.foo);   // one trailing comma

try {
    // two trailing commas is a SyntaxError
    eval("print({foo:'bar',,}.foo)");
} catch (e) {
    print(e.name);
}

/*===
1
2
3
4
5
6
7
===*/

/* Property name can be an identifier, a string, or a number.
 * The identifier can also be a reserved word.
 */

print({foo:1}.foo);
print({if:2}.if);
print({1:3}['1']);
print({1.23:4}['1.23']);   // coerced with ToString(1.23) -> '1.23'
print({1.00:5}['1']);      // coerced with ToString(1.00) -> '1'
print({Infinity:6}['Infinity']);
print({"foo":7}.foo);

/*===
1
2
3
4
5
6
7
===*/

/* Getter/setter name can be an identifier, a string, or a number.
 * The identifier can also be a reserved word.
 */

try {
    eval("print({get foo() { return 1 }}.foo);");
} catch (e) {
    print(e.name);
}

try {
    eval("print({get if() { return 2 }}.if);");
} catch (e) {
    print(e.name);
}

try {
    eval("print({get 1() { return 3 }}['1']);");
} catch (e) {
    print(e.name);
}

try {
    eval("print({get 1.23() { return 4 }}['1.23']);");  // coerced with ToString
} catch (e) {
    print(e.name);
}

try {
    eval("print({get 1.00() { return 5 }}['1']);");  // coerced with ToString
} catch (e) {
    print(e.name);
}

try {
    eval("print({get Infinity() { return 6 }}['Infinity']);");  // coerced with ToString
} catch (e) {
    print(e.name);
}

try {
    eval('print({get "foo"() { return 7 }}.foo);');
} catch (e) {
    print(e.name);
}

/*===
1
2
3
===*/

/* Some corner cases. */

try {
    eval("print({get: 1}.get);");                  // 'get' as a property name
} catch (e) {
    print(e.name);
}

try {
    eval("print({get foo() { return 2 }}.foo);");  // 'foo' as a getter
} catch (e) {
    print(e.name);
}

try {
    eval("print({get get() { return 3 }}.get);");  // 'get' as a getter name (pretty rare)
} catch (e) {
    print(e.name);
}

/*===
2
SyntaxError
===*/

/* Duplicate keys */

try {
    /* in non-strict mode, latter key should be effective */
    print(eval("function func1() { return ({foo:1,foo:2}).foo; }; func1();"));
} catch (e) {
    print(e.name);
}

try {
    /* in strict mode, it is a syntax error to have duplicate keys (among other things) */
    print(eval("function func2() { 'use strict'; return ({foo:1,foo:2}).foo; }; func2();"));
} catch (e) {
    print(e.name);
}

/*===
2
SyntaxError
SyntaxError
SyntaxError
SyntaxError
SyntaxError
SyntaxError
===*/

/* Duplicate keys and mixed set/get/plain key handling */

try {
    /* duplicate plain keys are allowed in non-strict mode, and last 
     * occurrence matters.
     */
    print(eval("({foo:1,foo:2}).foo"));
} catch (e) {
    print(e.name);
}

try {
    /* duplicate plain key in strict mode is a SyntaxError */
    print(eval("'use strict'; ({foo:1,foo:2}).foo"));
} catch (e) {
    print(e.name);
}

try {
    /* getter after plain not allowed */
    print(eval("({foo:1, get foo() { return 'getter'}}).foo"));
} catch (e) {
    print(e.name);
}

try {
    /* setter after plain not allowed */
    print(eval("({foo:1, set foo(v) {}}).foo"));
} catch (e) {
    print(e.name);
}

try {
    /* plain after getter not allowed */
    print(eval("({get foo() { return 'getter' }, foo:1}).foo"));
} catch (e) {
    print(e.name);
}

try {
    /* plain after setter not allowed */
    print(eval("({set foo(v) {}, foo:1}).foo"));
} catch (e) {
    print(e.name);
}

try {
    /* plain after getter and setter not allowed */
    print(eval("({get foo() { return 'getter' }, set foo(v) {}, foo:1}).foo"));
} catch (e) {
    print(e.name);
}

