summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/statements/for-of-iterator-close.js
blob: b28895d8fece37a3e6db93403befbc7b3ff953aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Tests that IteratorReturn is called when a for-of loop has an abrupt
// completion value during non-iterator code.

function test() {
    var returnCalled = 0;
    var returnCalledExpected = 0;
    var iterable = {};
    iterable[Symbol.iterator] = makeIterator({
        ret: function() {
            returnCalled++;
            return {};
        }
    });

    // break calls iter.return
    for (var x of iterable)
        break;
    assertEq(returnCalled, ++returnCalledExpected);

    // throw in body calls iter.return
    assertThrowsValue(function() {
        for (var x of iterable)
            throw "in body";
    }, "in body");
    assertEq(returnCalled, ++returnCalledExpected);

    // throw in lhs ref calls iter.return
    function throwlhs() {
        throw "in lhs";
    }
    assertThrowsValue(function() {
        for ((throwlhs()) of iterable)
            continue;
    }, "in lhs");
    assertEq(returnCalled, ++returnCalledExpected);

    // throw in iter.return doesn't re-call iter.return
    iterable[Symbol.iterator] = makeIterator({
        ret: function() {
            returnCalled++;
            throw "in iter.return";
        }
    });
    assertThrowsValue(function() {
        for (var x of iterable)
            break;
    }, "in iter.return");
    assertEq(returnCalled, ++returnCalledExpected);

    // throw in iter.next doesn't call IteratorClose
    iterable[Symbol.iterator] = makeIterator({
        next: function() {
            throw "in next";
        }
    });
    assertThrowsValue(function() {
        for (var x of iterable)
            break;
    }, "in next");
    assertEq(returnCalled, returnCalledExpected);

    // "return" must return an Object.
    iterable[Symbol.iterator] = makeIterator({
        ret: function() {
            returnCalled++;
            return 42;
        }
    });
    assertThrowsInstanceOf(function() {
        for (var x of iterable)
            break;
    }, TypeError);
    assertEq(returnCalled, ++returnCalledExpected);

    // continue doesn't call iter.return for the loop it's continuing
    var i = 0;
    iterable[Symbol.iterator] = makeIterator({
        next: function() {
            return { done: i++ > 5 };
        },
        ret: function() {
            returnCalled++;
            return {};
        }
    });
    for (var x of iterable)
        continue;
    assertEq(returnCalled, returnCalledExpected);

    // continue does call iter.return for loops it skips
    i = 0;
    L: do {
        for (var x of iterable)
            continue L;
    } while (false);
    assertEq(returnCalled, ++returnCalledExpected);
}

test();

if (typeof reportCompare === "function")
    reportCompare(0, 0);