
/*===
10
20
19
10
9
10
===*/

var x = 10;
print(x);
print(x-- + 10);
print(x++ + 10);
print((x)--);  // parens are OK
print((x)++);
print(x);

/*===
10
20
19
10
9
10
===*/

var obj = {x:10};
print(obj.x);
print(obj.x-- + 10);
print(obj.x++ + 10);
print((obj.x)--);
print((obj.x)++);
print(obj.x);

/*===
should print
ReferenceError
===*/

/* Invalid LHS parses but causes a run-time ReferenceError.
 *
 * Rhino and V8 don't print 'should print' which seems incorrect: the
 * UnaryExpression should be evaluated before the ReferenceError occurs.
 */

try {
    eval("print('should print')++;");
} catch (e) {
    print(e.name);
}

/*===
NaN NaN
NaN NaN
0 -1
0 1
0 -1
0 1
1 0
1 2
123 122
123 124
NaN NaN
NaN NaN
number 124
===*/

/* The value is coerced with ToNumber().  Note that the value assigned to
 * the post-increment/decrement is the previous value of the target, but
 * even that value will be coerced using ToNumber()!
 *
 * Hence, "y=undefined; print(y--)" will NOT print "undefined" but "NaN".
 */

var y;

y = undefined; print(y--, y);
y = undefined; print(y++, y);
y = null; print(y--, y);
y = null; print(y++, y);
y = false; print(y--, y);
y = false; print(y++, y);
y = true; print(y--, y);   // ToNumber(true) -> 1
y = true; print(y++, y);
y = '123'; print(y--, y);  // ToNumber('123') -> 123
y = '123'; print(y++, y);
y = 'foo'; print(y--, y);  // ToNumber('foo') -> NaN
y = 'foo'; print(y++, y);

y = '123'; print(typeof y++, y);  // ToNumber() is applied to OLD value too

/*===
1000
999
1000
1001
===*/

/* ToNumber() eventually calls valueOf().  Here ToNumber(obj) is thus 1000.
 */

obj = {};
obj.valueOf = function() {
    return 1000;
}
print(obj--);
print(obj);

obj = {};
obj.valueOf = function() {
    return 1000;
}
print(obj++);
print(obj);

/*===
eval
arguments
SyntaxError
SyntaxError
===*/

/* Attempt to use 'eval' or 'arguments' as an identifier name is
 * a SyntaxError in strict mode.
 */

var old_eval = eval;

try {
    // Note: this will clobber eval
    eval("function f1() { eval++; eval--; print('eval'); }; f1();");
} catch (e) {
    print(e.name);
}
eval = old_eval;

try {
    eval("function f2() { arguments++; arguments--; print('arguments'); }; f2();");
} catch (e) {
    print(e.name);
}

try {
    /* Rhino allows this, and clobbers eval in the process. */
    eval("function f3() { 'use strict'; eval++; eval--; }; f3();");
} catch (e) {
    print(e.name);
}
eval = old_eval;  // just in case

try {
    eval("function f4() { 'use strict'; arguments++; arguments--; }; f4();");
} catch (e) {
    print(e.name);
}

/*===
ReferenceError
11
===*/

/* Precedence: ++z++ parses as ++(z++).  The expression should cause a
 * ReferenceError because the result of "z++" won't be a valid LHS.
 * However, it is not a SyntaxError, and the postincrement SHOULD take
 * place.
 */

var z = 10;

try {
    /* Note: Rhino won't even parse this, so wrap in an eval to allow Rhino
     * testing of other cases here.
     *
     * Note: V8 will print '10' below, it will detect the invalid LHS case
     * without executing the postincrement.  This seems to be contrary to
     * the specification?
     */
    eval("print(++z++);");
} catch (e) {
    print(e.name);
}
print(z);

