| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 // Flags: --harmony-iteration | 28 // Flags: --harmony-iteration |
| 29 // Flags: --harmony-generators --harmony-scoping --harmony-proxies | 29 // Flags: --harmony-generators --harmony-scoping --harmony-proxies |
| 30 // Flags: --harmony-symbols |
| 30 | 31 |
| 31 // Test for-of semantics. | 32 // Test for-of semantics. |
| 32 | 33 |
| 33 "use strict"; | 34 "use strict"; |
| 34 | 35 |
| 35 | 36 |
| 36 // First, some helpers. | 37 // First, some helpers. |
| 37 | 38 |
| 38 function* values() { | 39 function* values() { |
| 39 for (var i = 0; i < arguments.length; i++) { | 40 for (var i = 0; i < arguments.length; i++) { |
| 40 yield arguments[i]; | 41 yield arguments[i]; |
| 41 } | 42 } |
| 42 } | 43 } |
| 43 | 44 |
| 45 function wrap_iterator(iterator) { |
| 46 var iterable = {}; |
| 47 iterable[Symbol.iterator] = function() { return iterator; }; |
| 48 return iterable; |
| 49 } |
| 50 |
| 44 function integers_until(max) { | 51 function integers_until(max) { |
| 45 function next() { | 52 function next() { |
| 46 var ret = { value: this.n, done: this.n == max }; | 53 var ret = { value: this.n, done: this.n == max }; |
| 47 this.n++; | 54 this.n++; |
| 48 return ret; | 55 return ret; |
| 49 } | 56 } |
| 50 return { next: next, n: 0 } | 57 return wrap_iterator({ next: next, n: 0 }); |
| 51 } | 58 } |
| 52 | 59 |
| 53 function results(results) { | 60 function results(results) { |
| 54 var i = 0; | 61 var i = 0; |
| 55 function next() { | 62 function next() { |
| 56 return results[i++]; | 63 return results[i++]; |
| 57 } | 64 } |
| 58 return { next: next } | 65 return wrap_iterator({ next: next }); |
| 59 } | 66 } |
| 60 | 67 |
| 61 function* integers_from(n) { | 68 function* integers_from(n) { |
| 62 while (1) yield n++; | 69 while (1) yield n++; |
| 63 } | 70 } |
| 64 | 71 |
| 65 // A destructive append. | 72 // A destructive append. |
| 66 function append(x, tail) { | 73 function append(x, tail) { |
| 67 tail[tail.length] = x; | 74 tail[tail.length] = x; |
| 68 return tail; | 75 return tail; |
| 69 } | 76 } |
| 70 | 77 |
| 71 function sum(x, tail) { | 78 function sum(x, tail) { |
| 72 return x + tail; | 79 return x + tail; |
| 73 } | 80 } |
| 74 | 81 |
| 75 function fold(cons, seed, iter) { | 82 function fold(cons, seed, iterable) { |
| 76 for (var x of iter) { | 83 for (var x of iterable) { |
| 77 seed = cons(x, seed); | 84 seed = cons(x, seed); |
| 78 } | 85 } |
| 79 return seed; | 86 return seed; |
| 80 } | 87 } |
| 81 | 88 |
| 82 function* take(iter, n) { | 89 function* take(iterable, n) { |
| 83 if (n == 0) return; | 90 if (n == 0) return; |
| 84 for (let x of iter) { | 91 for (let x of iterable) { |
| 85 yield x; | 92 yield x; |
| 86 if (--n == 0) break; | 93 if (--n == 0) break; |
| 87 } | 94 } |
| 88 } | 95 } |
| 89 | 96 |
| 90 function nth(iter, n) { | 97 function nth(iterable, n) { |
| 91 for (let x of iter) { | 98 for (let x of iterable) { |
| 92 if (n-- == 0) return x; | 99 if (n-- == 0) return x; |
| 93 } | 100 } |
| 94 throw "unreachable"; | 101 throw "unreachable"; |
| 95 } | 102 } |
| 96 | 103 |
| 97 function* skip_every(iter, n) { | 104 function* skip_every(iterable, n) { |
| 98 var i = 0; | 105 var i = 0; |
| 99 for (let x of iter) { | 106 for (let x of iterable) { |
| 100 if (++i % n == 0) continue; | 107 if (++i % n == 0) continue; |
| 101 yield x; | 108 yield x; |
| 102 } | 109 } |
| 103 } | 110 } |
| 104 | 111 |
| 105 function* iter_map(iter, f) { | 112 function* iter_map(iterable, f) { |
| 106 for (var x of iter) { | 113 for (var x of iterable) { |
| 107 yield f(x); | 114 yield f(x); |
| 108 } | 115 } |
| 109 } | 116 } |
| 110 function nested_fold(cons, seed, iter) { | 117 function nested_fold(cons, seed, iterable) { |
| 111 var visited = [] | 118 var visited = [] |
| 112 for (let x of iter) { | 119 for (let x of iterable) { |
| 113 for (let y of x) { | 120 for (let y of x) { |
| 114 seed = cons(y, seed); | 121 seed = cons(y, seed); |
| 115 } | 122 } |
| 116 } | 123 } |
| 117 return seed; | 124 return seed; |
| 118 } | 125 } |
| 119 | 126 |
| 120 function* unreachable(iter) { | 127 function* unreachable(iterable) { |
| 121 for (let x of iter) { | 128 for (let x of iterable) { |
| 122 throw "not reached"; | 129 throw "not reached"; |
| 123 } | 130 } |
| 124 } | 131 } |
| 125 | 132 |
| 126 function one_time_getter(o, prop, val) { | 133 function one_time_getter(o, prop, val) { |
| 127 function set_never() { throw "unreachable"; } | 134 function set_never() { throw "unreachable"; } |
| 128 var gotten = false; | 135 var gotten = false; |
| 129 function get_once() { | 136 function get_once() { |
| 130 if (gotten) throw "got twice"; | 137 if (gotten) throw "got twice"; |
| 131 gotten = true; | 138 gotten = true; |
| 132 return val; | 139 return val; |
| 133 } | 140 } |
| 134 Object.defineProperty(o, prop, {get: get_once, set: set_never}) | 141 Object.defineProperty(o, prop, {get: get_once, set: set_never}) |
| 135 return o; | 142 return o; |
| 136 } | 143 } |
| 137 | 144 |
| 138 function never_getter(o, prop) { | 145 function never_getter(o, prop) { |
| 139 function never() { throw "unreachable"; } | 146 function never() { throw "unreachable"; } |
| 140 Object.defineProperty(o, prop, {get: never, set: never}) | 147 Object.defineProperty(o, prop, {get: never, set: never}) |
| 141 return o; | 148 return o; |
| 142 } | 149 } |
| 143 | 150 |
| 144 function remove_next_after(iter, n) { | 151 function remove_next_after(iterable, n) { |
| 152 var iterator = iterable[Symbol.iterator](); |
| 145 function next() { | 153 function next() { |
| 146 if (n-- == 0) delete this.next; | 154 if (n-- == 0) delete this.next; |
| 147 return iter.next(); | 155 return iterator.next(); |
| 148 } | 156 } |
| 149 return { next: next } | 157 return wrap_iterator({ next: next }); |
| 150 } | 158 } |
| 151 | 159 |
| 152 function poison_next_after(iter, n) { | 160 function poison_next_after(iterable, n) { |
| 161 var iterator = iterable[Symbol.iterator](); |
| 153 function next() { | 162 function next() { |
| 154 return iter.next(); | 163 return iterator.next(); |
| 155 } | 164 } |
| 156 function next_getter() { | 165 function next_getter() { |
| 157 if (n-- < 0) | 166 if (n-- < 0) |
| 158 throw "poisoned"; | 167 throw "poisoned"; |
| 159 return next; | 168 return next; |
| 160 } | 169 } |
| 161 var o = {}; | 170 var o = {}; |
| 162 Object.defineProperty(o, 'next', { get: next_getter }); | 171 Object.defineProperty(o, 'next', { get: next_getter }); |
| 163 return o; | 172 return wrap_iterator(o); |
| 164 } | 173 } |
| 165 | 174 |
| 166 // Now, the tests. | 175 // Now, the tests. |
| 167 | 176 |
| 168 // Non-generator iterators. | 177 // Non-generator iterators. |
| 169 assertEquals(45, fold(sum, 0, integers_until(10))); | 178 assertEquals(45, fold(sum, 0, integers_until(10))); |
| 170 // Generator iterators. | 179 // Generator iterators. |
| 171 assertEquals([1, 2, 3], fold(append, [], values(1, 2, 3))); | 180 assertEquals([1, 2, 3], fold(append, [], values(1, 2, 3))); |
| 172 // Break. | 181 // Break. |
| 173 assertEquals(45, fold(sum, 0, take(integers_from(0), 10))); | 182 assertEquals(45, fold(sum, 0, take(integers_from(0), 10))); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 // "next" is looked up each time. | 225 // "next" is looked up each time. |
| 217 assertThrows('fold(sum, 0, remove_next_after(integers_until(10), 5))', | 226 assertThrows('fold(sum, 0, remove_next_after(integers_until(10), 5))', |
| 218 TypeError); | 227 TypeError); |
| 219 // It is not called at any other time. | 228 // It is not called at any other time. |
| 220 assertEquals(45, | 229 assertEquals(45, |
| 221 fold(sum, 0, remove_next_after(integers_until(10), 10))); | 230 fold(sum, 0, remove_next_after(integers_until(10), 10))); |
| 222 // It is not looked up too many times. | 231 // It is not looked up too many times. |
| 223 assertEquals(45, | 232 assertEquals(45, |
| 224 fold(sum, 0, poison_next_after(integers_until(10), 10))); | 233 fold(sum, 0, poison_next_after(integers_until(10), 10))); |
| 225 | 234 |
| 226 function labelled_continue(iter) { | 235 function labelled_continue(iterable) { |
| 227 var n = 0; | 236 var n = 0; |
| 228 outer: | 237 outer: |
| 229 while (true) { | 238 while (true) { |
| 230 n++; | 239 n++; |
| 231 for (var x of iter) continue outer; | 240 for (var x of iterable) continue outer; |
| 232 break; | 241 break; |
| 233 } | 242 } |
| 234 return n; | 243 return n; |
| 235 } | 244 } |
| 236 assertEquals(11, labelled_continue(integers_until(10))); | 245 assertEquals(11, labelled_continue(integers_until(10))); |
| 237 | 246 |
| 238 function labelled_break(iter) { | 247 function labelled_break(iterable) { |
| 239 var n = 0; | 248 var n = 0; |
| 240 outer: | 249 outer: |
| 241 while (true) { | 250 while (true) { |
| 242 n++; | 251 n++; |
| 243 for (var x of iter) break outer; | 252 for (var x of iterable) break outer; |
| 244 } | 253 } |
| 245 return n; | 254 return n; |
| 246 } | 255 } |
| 247 assertEquals(1, labelled_break(integers_until(10))); | 256 assertEquals(1, labelled_break(integers_until(10))); |
| 248 | 257 |
| 249 // Test continue/break in catch. | 258 // Test continue/break in catch. |
| 250 function catch_control(iter, k) { | 259 function catch_control(iterable, k) { |
| 251 var n = 0; | 260 var n = 0; |
| 252 for (var x of iter) { | 261 for (var x of iterable) { |
| 253 try { | 262 try { |
| 254 return k(x); | 263 return k(x); |
| 255 } catch (e) { | 264 } catch (e) { |
| 256 if (e == "continue") continue; | 265 if (e == "continue") continue; |
| 257 else if (e == "break") break; | 266 else if (e == "break") break; |
| 258 else throw e; | 267 else throw e; |
| 259 } | 268 } |
| 260 } while (false); | 269 } while (false); |
| 261 return false; | 270 return false; |
| 262 } | 271 } |
| 263 assertEquals(false, | 272 assertEquals(false, |
| 264 catch_control(integers_until(10), | 273 catch_control(integers_until(10), |
| 265 function() { throw "break" })); | 274 function() { throw "break" })); |
| 266 assertEquals(false, | 275 assertEquals(false, |
| 267 catch_control(integers_until(10), | 276 catch_control(integers_until(10), |
| 268 function() { throw "continue" })); | 277 function() { throw "continue" })); |
| 269 assertEquals(5, | 278 assertEquals(5, |
| 270 catch_control(integers_until(10), | 279 catch_control(integers_until(10), |
| 271 function(x) { | 280 function(x) { |
| 272 if (x == 5) return x; | 281 if (x == 5) return x; |
| 273 throw "continue"; | 282 throw "continue"; |
| 274 })); | 283 })); |
| 275 | 284 |
| 276 // Test continue/break in try. | 285 // Test continue/break in try. |
| 277 function try_control(iter, k) { | 286 function try_control(iterable, k) { |
| 278 var n = 0; | 287 var n = 0; |
| 279 for (var x of iter) { | 288 for (var x of iterable) { |
| 280 try { | 289 try { |
| 281 var e = k(x); | 290 var e = k(x); |
| 282 if (e == "continue") continue; | 291 if (e == "continue") continue; |
| 283 else if (e == "break") break; | 292 else if (e == "break") break; |
| 284 return e; | 293 return e; |
| 285 } catch (e) { | 294 } catch (e) { |
| 286 throw e; | 295 throw e; |
| 287 } | 296 } |
| 288 } while (false); | 297 } while (false); |
| 289 return false; | 298 return false; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 306 } | 315 } |
| 307 assertEquals([1, 2], | 316 assertEquals([1, 2], |
| 308 fold(append, [], | 317 fold(append, [], |
| 309 results([one_time_getter({ value: 1 }, 'done', false), | 318 results([one_time_getter({ value: 1 }, 'done', false), |
| 310 one_time_getter({ done: false }, 'value', 2), | 319 one_time_getter({ done: false }, 'value', 2), |
| 311 { value: 37, done: true }, | 320 { value: 37, done: true }, |
| 312 never_getter(never_getter({}, 'done'), 'value')] | 321 never_getter(never_getter({}, 'done'), 'value')] |
| 313 .map(transparent_proxy)))); | 322 .map(transparent_proxy)))); |
| 314 | 323 |
| 315 // Proxy iterators. | 324 // Proxy iterators. |
| 316 function poison_proxy_after(x, n) { | 325 function poison_proxy_after(iterable, n) { |
| 317 return Proxy.create({ | 326 var iterator = iterable[Symbol.iterator](); |
| 327 return wrap_iterator(Proxy.create({ |
| 318 get: function(receiver, name) { | 328 get: function(receiver, name) { |
| 319 if (name == 'next' && n-- < 0) throw "unreachable"; | 329 if (name == 'next' && n-- < 0) throw "unreachable"; |
| 320 return x[name]; | 330 return iterator[name]; |
| 321 }, | 331 }, |
| 322 // Needed for integers_until(10)'s this.n++. | 332 // Needed for integers_until(10)'s this.n++. |
| 323 set: function(receiver, name, val) { | 333 set: function(receiver, name, val) { |
| 324 return x[name] = val; | 334 return iterator[name] = val; |
| 325 } | 335 } |
| 326 }); | 336 })); |
| 327 } | 337 } |
| 328 assertEquals(45, fold(sum, 0, poison_proxy_after(integers_until(10), 10))); | 338 assertEquals(45, fold(sum, 0, poison_proxy_after(integers_until(10), 10))); |
| OLD | NEW |