OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 // Flags: --harmony-generators --expose-gc |
| 29 |
| 30 // Test generator iteration. |
| 31 |
| 32 var GeneratorFunction = (function*(){yield 1;}).__proto__.constructor; |
| 33 |
| 34 function TestGenerator(g, expected_values_for_next, |
| 35 send_val, expected_values_for_send) { |
| 36 function testNext(thunk) { |
| 37 var iter = thunk(); |
| 38 for (var i = 0; i < expected_values_for_next.length; i++) { |
| 39 assertEquals(expected_values_for_next[i], iter.next()); |
| 40 } |
| 41 assertThrows(function() { iter.next(); }, Error); |
| 42 } |
| 43 function testSend(thunk) { |
| 44 var iter = thunk(); |
| 45 for (var i = 0; i < expected_values_for_send.length; i++) { |
| 46 assertEquals(expected_values_for_send[i], iter.send(send_val)); |
| 47 } |
| 48 assertThrows(function() { iter.send(send_val); }, Error); |
| 49 } |
| 50 function testThrow(thunk) { |
| 51 for (var i = 0; i < expected_values_for_next.length; i++) { |
| 52 var iter = thunk(); |
| 53 for (var j = 0; j < i; j++) { |
| 54 assertEquals(expected_values_for_next[j], iter.next()); |
| 55 } |
| 56 function Sentinel() {} |
| 57 assertThrows(function () { iter.throw(new Sentinel); }, Sentinel); |
| 58 assertThrows(function () { iter.next(); }, Error); |
| 59 } |
| 60 } |
| 61 |
| 62 testNext(g); |
| 63 testSend(g); |
| 64 testThrow(g); |
| 65 |
| 66 if (g instanceof GeneratorFunction) { |
| 67 testNext(function() { return new g(); }); |
| 68 testSend(function() { return new g(); }); |
| 69 testThrow(function() { return new g(); }); |
| 70 } |
| 71 } |
| 72 |
| 73 TestGenerator(function* g1() { }, |
| 74 [undefined], |
| 75 "foo", |
| 76 [undefined]); |
| 77 |
| 78 TestGenerator(function* g2() { yield 1; }, |
| 79 [1, undefined], |
| 80 "foo", |
| 81 [1, undefined]); |
| 82 |
| 83 TestGenerator(function* g3() { yield 1; yield 2; }, |
| 84 [1, 2, undefined], |
| 85 "foo", |
| 86 [1, 2, undefined]); |
| 87 |
| 88 TestGenerator(function* g4() { yield 1; yield 2; return 3; }, |
| 89 [1, 2, 3], |
| 90 "foo", |
| 91 [1, 2, 3]); |
| 92 |
| 93 TestGenerator(function* g5() { return 1; }, |
| 94 [1], |
| 95 "foo", |
| 96 [1]); |
| 97 |
| 98 TestGenerator(function* g6() { var x = yield 1; return x; }, |
| 99 [1, undefined], |
| 100 "foo", |
| 101 [1, "foo"]); |
| 102 |
| 103 TestGenerator(function* g7() { var x = yield 1; yield 2; return x; }, |
| 104 [1, 2, undefined], |
| 105 "foo", |
| 106 [1, 2, "foo"]); |
| 107 |
| 108 TestGenerator(function* g8() { for (var x = 0; x < 4; x++) { yield x; } }, |
| 109 [0, 1, 2, 3, undefined], |
| 110 "foo", |
| 111 [0, 1, 2, 3, undefined]); |
| 112 |
| 113 // Generator with arguments. |
| 114 TestGenerator( |
| 115 function g9() { |
| 116 return (function*(a, b, c, d) { |
| 117 yield a; yield b; yield c; yield d; |
| 118 })("fee", "fi", "fo", "fum"); |
| 119 }, |
| 120 ["fee", "fi", "fo", "fum", undefined], |
| 121 "foo", |
| 122 ["fee", "fi", "fo", "fum", undefined]); |
| 123 |
| 124 // Too few arguments. |
| 125 TestGenerator( |
| 126 function g10() { |
| 127 return (function*(a, b, c, d) { |
| 128 yield a; yield b; yield c; yield d; |
| 129 })("fee", "fi"); |
| 130 }, |
| 131 ["fee", "fi", undefined, undefined, undefined], |
| 132 "foo", |
| 133 ["fee", "fi", undefined, undefined, undefined]); |
| 134 |
| 135 // Too many arguments. |
| 136 TestGenerator( |
| 137 function g11() { |
| 138 return (function*(a, b, c, d) { |
| 139 yield a; yield b; yield c; yield d; |
| 140 })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman"); |
| 141 }, |
| 142 ["fee", "fi", "fo", "fum", undefined], |
| 143 "foo", |
| 144 ["fee", "fi", "fo", "fum", undefined]); |
| 145 |
| 146 // The arguments object. |
| 147 TestGenerator( |
| 148 function g12() { |
| 149 return (function*(a, b, c, d) { |
| 150 for (var i = 0; i < arguments.length; i++) { |
| 151 yield arguments[i]; |
| 152 } |
| 153 })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman"); |
| 154 }, |
| 155 ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman", |
| 156 undefined], |
| 157 "foo", |
| 158 ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman", |
| 159 undefined]); |
| 160 |
| 161 // Access to captured free variables. |
| 162 TestGenerator( |
| 163 function g13() { |
| 164 return (function(a, b, c, d) { |
| 165 return (function*() { |
| 166 yield a; yield b; yield c; yield d; |
| 167 })(); |
| 168 })("fee", "fi", "fo", "fum"); |
| 169 }, |
| 170 ["fee", "fi", "fo", "fum", undefined], |
| 171 "foo", |
| 172 ["fee", "fi", "fo", "fum", undefined]); |
| 173 |
| 174 // Abusing the arguments object. |
| 175 TestGenerator( |
| 176 function g14() { |
| 177 return (function*(a, b, c, d) { |
| 178 arguments[0] = "Be he live"; |
| 179 arguments[1] = "or be he dead"; |
| 180 arguments[2] = "I'll grind his bones"; |
| 181 arguments[3] = "to make my bread"; |
| 182 yield a; yield b; yield c; yield d; |
| 183 })("fee", "fi", "fo", "fum"); |
| 184 }, |
| 185 ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread", |
| 186 undefined], |
| 187 "foo", |
| 188 ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread", |
| 189 undefined]); |
| 190 |
| 191 // Abusing the arguments object: strict mode. |
| 192 TestGenerator( |
| 193 function g15() { |
| 194 return (function*(a, b, c, d) { |
| 195 "use strict"; |
| 196 arguments[0] = "Be he live"; |
| 197 arguments[1] = "or be he dead"; |
| 198 arguments[2] = "I'll grind his bones"; |
| 199 arguments[3] = "to make my bread"; |
| 200 yield a; yield b; yield c; yield d; |
| 201 })("fee", "fi", "fo", "fum"); |
| 202 }, |
| 203 ["fee", "fi", "fo", "fum", undefined], |
| 204 "foo", |
| 205 ["fee", "fi", "fo", "fum", undefined]); |
| 206 |
| 207 // GC. |
| 208 TestGenerator(function* g16() { yield "baz"; gc(); yield "qux"; }, |
| 209 ["baz", "qux", undefined], |
| 210 "foo", |
| 211 ["baz", "qux", undefined]); |
| 212 |
| 213 // Receivers. |
| 214 function TestReceivers() { |
| 215 TestGenerator( |
| 216 function g17() { |
| 217 function* g() { yield this.x; yield this.y; } |
| 218 var o = { start: g, x: 1, y: 2 }; |
| 219 return o.start(); |
| 220 }, |
| 221 [1, 2, undefined], |
| 222 "foo", |
| 223 [1, 2, undefined]); |
| 224 |
| 225 TestGenerator( |
| 226 function g18() { |
| 227 function* g() { yield this.x; yield this.y; } |
| 228 var iter = new g; |
| 229 iter.x = 1; |
| 230 iter.y = 2; |
| 231 return iter; |
| 232 }, |
| 233 [1, 2, undefined], |
| 234 "foo", |
| 235 [1, 2, undefined]); |
| 236 } |
| 237 // TODO(wingo): Enable this test. Currently accessing "this" doesn't work as |
| 238 // prior to generators, nothing needed to heap-allocate the receiver. |
| 239 // TestReceivers(); |
| 240 |
| 241 function TestRecursion() { |
| 242 function TestNextRecursion() { |
| 243 function* g() { yield iter.next(); } |
| 244 var iter = g(); |
| 245 return iter.next(); |
| 246 } |
| 247 function TestSendRecursion() { |
| 248 function* g() { yield iter.send(42); } |
| 249 var iter = g(); |
| 250 return iter.next(); |
| 251 } |
| 252 function TestThrowRecursion() { |
| 253 function* g() { yield iter.throw(1); } |
| 254 var iter = g(); |
| 255 return iter.next(); |
| 256 } |
| 257 assertThrows(TestNextRecursion, Error); |
| 258 assertThrows(TestSendRecursion, Error); |
| 259 assertThrows(TestThrowRecursion, Error); |
| 260 } |
| 261 TestRecursion(); |
OLD | NEW |