/*===
-Infinity -Infinity string 0 
-Infinity -7 string 0 
-Infinity -6 string 0 
-Infinity -5 string 0 
-Infinity -4 string 0 
-Infinity -3 string 0 
-Infinity -2 string 0 
-Infinity -1 string 0 
-Infinity 0 string 0 
-Infinity 0 string 0 
-Infinity 1 string 1 f
-Infinity 2 string 2 fo
-Infinity 3 string 3 foo
-Infinity 4 string 4 foob
-Infinity 5 string 5 fooba
-Infinity 6 string 6 foobar
-Infinity 7 string 6 foobar
-Infinity Infinity string 6 foobar
-Infinity NaN string 0 
-7 -Infinity string 0 
-7 -7 string 0 
-7 -6 string 0 
-7 -5 string 0 
-7 -4 string 0 
-7 -3 string 0 
-7 -2 string 0 
-7 -1 string 0 
-7 0 string 0 
-7 0 string 0 
-7 1 string 1 f
-7 2 string 2 fo
-7 3 string 3 foo
-7 4 string 4 foob
-7 5 string 5 fooba
-7 6 string 6 foobar
-7 7 string 6 foobar
-7 Infinity string 6 foobar
-7 NaN string 0 
-6 -Infinity string 0 
-6 -7 string 0 
-6 -6 string 0 
-6 -5 string 0 
-6 -4 string 0 
-6 -3 string 0 
-6 -2 string 0 
-6 -1 string 0 
-6 0 string 0 
-6 0 string 0 
-6 1 string 1 f
-6 2 string 2 fo
-6 3 string 3 foo
-6 4 string 4 foob
-6 5 string 5 fooba
-6 6 string 6 foobar
-6 7 string 6 foobar
-6 Infinity string 6 foobar
-6 NaN string 0 
-5 -Infinity string 0 
-5 -7 string 0 
-5 -6 string 0 
-5 -5 string 0 
-5 -4 string 0 
-5 -3 string 0 
-5 -2 string 0 
-5 -1 string 0 
-5 0 string 0 
-5 0 string 0 
-5 1 string 1 f
-5 2 string 2 fo
-5 3 string 3 foo
-5 4 string 4 foob
-5 5 string 5 fooba
-5 6 string 6 foobar
-5 7 string 6 foobar
-5 Infinity string 6 foobar
-5 NaN string 0 
-4 -Infinity string 0 
-4 -7 string 0 
-4 -6 string 0 
-4 -5 string 0 
-4 -4 string 0 
-4 -3 string 0 
-4 -2 string 0 
-4 -1 string 0 
-4 0 string 0 
-4 0 string 0 
-4 1 string 1 f
-4 2 string 2 fo
-4 3 string 3 foo
-4 4 string 4 foob
-4 5 string 5 fooba
-4 6 string 6 foobar
-4 7 string 6 foobar
-4 Infinity string 6 foobar
-4 NaN string 0 
-3 -Infinity string 0 
-3 -7 string 0 
-3 -6 string 0 
-3 -5 string 0 
-3 -4 string 0 
-3 -3 string 0 
-3 -2 string 0 
-3 -1 string 0 
-3 0 string 0 
-3 0 string 0 
-3 1 string 1 f
-3 2 string 2 fo
-3 3 string 3 foo
-3 4 string 4 foob
-3 5 string 5 fooba
-3 6 string 6 foobar
-3 7 string 6 foobar
-3 Infinity string 6 foobar
-3 NaN string 0 
-2 -Infinity string 0 
-2 -7 string 0 
-2 -6 string 0 
-2 -5 string 0 
-2 -4 string 0 
-2 -3 string 0 
-2 -2 string 0 
-2 -1 string 0 
-2 0 string 0 
-2 0 string 0 
-2 1 string 1 f
-2 2 string 2 fo
-2 3 string 3 foo
-2 4 string 4 foob
-2 5 string 5 fooba
-2 6 string 6 foobar
-2 7 string 6 foobar
-2 Infinity string 6 foobar
-2 NaN string 0 
-1 -Infinity string 0 
-1 -7 string 0 
-1 -6 string 0 
-1 -5 string 0 
-1 -4 string 0 
-1 -3 string 0 
-1 -2 string 0 
-1 -1 string 0 
-1 0 string 0 
-1 0 string 0 
-1 1 string 1 f
-1 2 string 2 fo
-1 3 string 3 foo
-1 4 string 4 foob
-1 5 string 5 fooba
-1 6 string 6 foobar
-1 7 string 6 foobar
-1 Infinity string 6 foobar
-1 NaN string 0 
0 -Infinity string 0 
0 -7 string 0 
0 -6 string 0 
0 -5 string 0 
0 -4 string 0 
0 -3 string 0 
0 -2 string 0 
0 -1 string 0 
0 0 string 0 
0 0 string 0 
0 1 string 1 f
0 2 string 2 fo
0 3 string 3 foo
0 4 string 4 foob
0 5 string 5 fooba
0 6 string 6 foobar
0 7 string 6 foobar
0 Infinity string 6 foobar
0 NaN string 0 
0 -Infinity string 0 
0 -7 string 0 
0 -6 string 0 
0 -5 string 0 
0 -4 string 0 
0 -3 string 0 
0 -2 string 0 
0 -1 string 0 
0 0 string 0 
0 0 string 0 
0 1 string 1 f
0 2 string 2 fo
0 3 string 3 foo
0 4 string 4 foob
0 5 string 5 fooba
0 6 string 6 foobar
0 7 string 6 foobar
0 Infinity string 6 foobar
0 NaN string 0 
1 -Infinity string 1 f
1 -7 string 1 f
1 -6 string 1 f
1 -5 string 1 f
1 -4 string 1 f
1 -3 string 1 f
1 -2 string 1 f
1 -1 string 1 f
1 0 string 1 f
1 0 string 1 f
1 1 string 0 
1 2 string 1 o
1 3 string 2 oo
1 4 string 3 oob
1 5 string 4 ooba
1 6 string 5 oobar
1 7 string 5 oobar
1 Infinity string 5 oobar
1 NaN string 1 f
2 -Infinity string 2 fo
2 -7 string 2 fo
2 -6 string 2 fo
2 -5 string 2 fo
2 -4 string 2 fo
2 -3 string 2 fo
2 -2 string 2 fo
2 -1 string 2 fo
2 0 string 2 fo
2 0 string 2 fo
2 1 string 1 o
2 2 string 0 
2 3 string 1 o
2 4 string 2 ob
2 5 string 3 oba
2 6 string 4 obar
2 7 string 4 obar
2 Infinity string 4 obar
2 NaN string 2 fo
3 -Infinity string 3 foo
3 -7 string 3 foo
3 -6 string 3 foo
3 -5 string 3 foo
3 -4 string 3 foo
3 -3 string 3 foo
3 -2 string 3 foo
3 -1 string 3 foo
3 0 string 3 foo
3 0 string 3 foo
3 1 string 2 oo
3 2 string 1 o
3 3 string 0 
3 4 string 1 b
3 5 string 2 ba
3 6 string 3 bar
3 7 string 3 bar
3 Infinity string 3 bar
3 NaN string 3 foo
4 -Infinity string 4 foob
4 -7 string 4 foob
4 -6 string 4 foob
4 -5 string 4 foob
4 -4 string 4 foob
4 -3 string 4 foob
4 -2 string 4 foob
4 -1 string 4 foob
4 0 string 4 foob
4 0 string 4 foob
4 1 string 3 oob
4 2 string 2 ob
4 3 string 1 b
4 4 string 0 
4 5 string 1 a
4 6 string 2 ar
4 7 string 2 ar
4 Infinity string 2 ar
4 NaN string 4 foob
5 -Infinity string 5 fooba
5 -7 string 5 fooba
5 -6 string 5 fooba
5 -5 string 5 fooba
5 -4 string 5 fooba
5 -3 string 5 fooba
5 -2 string 5 fooba
5 -1 string 5 fooba
5 0 string 5 fooba
5 0 string 5 fooba
5 1 string 4 ooba
5 2 string 3 oba
5 3 string 2 ba
5 4 string 1 a
5 5 string 0 
5 6 string 1 r
5 7 string 1 r
5 Infinity string 1 r
5 NaN string 5 fooba
6 -Infinity string 6 foobar
6 -7 string 6 foobar
6 -6 string 6 foobar
6 -5 string 6 foobar
6 -4 string 6 foobar
6 -3 string 6 foobar
6 -2 string 6 foobar
6 -1 string 6 foobar
6 0 string 6 foobar
6 0 string 6 foobar
6 1 string 5 oobar
6 2 string 4 obar
6 3 string 3 bar
6 4 string 2 ar
6 5 string 1 r
6 6 string 0 
6 7 string 0 
6 Infinity string 0 
6 NaN string 6 foobar
7 -Infinity string 6 foobar
7 -7 string 6 foobar
7 -6 string 6 foobar
7 -5 string 6 foobar
7 -4 string 6 foobar
7 -3 string 6 foobar
7 -2 string 6 foobar
7 -1 string 6 foobar
7 0 string 6 foobar
7 0 string 6 foobar
7 1 string 5 oobar
7 2 string 4 obar
7 3 string 3 bar
7 4 string 2 ar
7 5 string 1 r
7 6 string 0 
7 7 string 0 
7 Infinity string 0 
7 NaN string 6 foobar
Infinity -Infinity string 6 foobar
Infinity -7 string 6 foobar
Infinity -6 string 6 foobar
Infinity -5 string 6 foobar
Infinity -4 string 6 foobar
Infinity -3 string 6 foobar
Infinity -2 string 6 foobar
Infinity -1 string 6 foobar
Infinity 0 string 6 foobar
Infinity 0 string 6 foobar
Infinity 1 string 5 oobar
Infinity 2 string 4 obar
Infinity 3 string 3 bar
Infinity 4 string 2 ar
Infinity 5 string 1 r
Infinity 6 string 0 
Infinity 7 string 0 
Infinity Infinity string 0 
Infinity NaN string 6 foobar
NaN -Infinity string 0 
NaN -7 string 0 
NaN -6 string 0 
NaN -5 string 0 
NaN -4 string 0 
NaN -3 string 0 
NaN -2 string 0 
NaN -1 string 0 
NaN 0 string 0 
NaN 0 string 0 
NaN 1 string 1 f
NaN 2 string 2 fo
NaN 3 string 3 foo
NaN 4 string 4 foob
NaN 5 string 5 fooba
NaN 6 string 6 foobar
NaN 7 string 6 foobar
NaN Infinity string 6 foobar
NaN NaN string 0 
===*/

function basicTest() {
    var numbers = [
        Number.NEGATIVE_INFINITY, -7, -6, -5, -4, -3, -2, -1,
        -0, +0, 1, 2, 3, 4, 5, 6, 7, Number.POSITIVE_INFINITY, Number.NaN
    ];
    var i, j;

    function test(str, start, end) {
        var t = str.substring(start, end);
        print(start, end, typeof t, t.length, t);
    }

    for (i = 0; i < numbers.length; i++) {
        for (j = 0; j < numbers.length; j++) {
            test('foobar', numbers[i], numbers[j]);
        }
    }
}

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

/*===
string 2 97 114
string 2 4660 98
===*/

/* Non-BMP test. */

function nonBmpTest() {
    var str = new String('foo\u1234bar');
    var t;

    t = str.substring(5, 7);
    print(typeof t, t.length, t.charCodeAt(0), t.charCodeAt(1));

    t = str.substring(5, 3);
    print(typeof t, t.length, t.charCodeAt(0), t.charCodeAt(1));
}

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

/*===
TypeError
TypeError
string 2 ue
string 2 ls
string 2 34
string 2 ob
string 2 2,
string 2 bj
toString() this
valueOf() start
valueOf() end
string 2 ba
===*/

function coercionTest() {
    function test(str, start, end) {
        var t;

        try {
            t = String.prototype.substring.call(str, start, end);
            print(typeof t, t.length, t);
        } catch (e) {
            print(e.name);
        }
    }

    test(undefined, 2, 4);
    test(null, 2, 4);
    test(true, 2, 4);
    test(false, 2, 4);
    test(12345, 2, 4);
    test('foobar', 2, 4);
    test([1,2,3,4], 2, 4);
    test({ foo: 1, bar: 2}, 2, 4);

    test({ toString: function() { print('toString() this'); return 'foobar' },
           valueOf: function() { print('valueOf() this'); return 'barfoo' } },
         { toString: function() { print('toString() start'); return 2; },
           valueOf: function() { print('valueOf() start'); return 3; } },
         { toString: function() { print('toString() end'); return 4; },
           valueOf: function() { print('valueOf() end'); return 5; } });
}

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