Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Unified Diff: test/mjsunit/harmony/iteration-semantics.js

Issue 15288011: Baseline for-of implementation (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: s/syntax/semantics/ Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/mjsunit/harmony/iteration-semantics.js
diff --git a/test/mjsunit/harmony/iteration-semantics.js b/test/mjsunit/harmony/iteration-semantics.js
new file mode 100644
index 0000000000000000000000000000000000000000..6215522a41bd6c3eaee25c409bcdc1e14874a710
--- /dev/null
+++ b/test/mjsunit/harmony/iteration-semantics.js
@@ -0,0 +1,327 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony
+
+// Test for-of semantics.
+
+"use strict";
+
+
+// First, some helpers.
+
+function* values() {
+ for (var i = 0; i < arguments.length; i++) {
+ yield arguments[i];
+ }
+}
+
+function integers_until(max) {
+ function next() {
+ var ret = { value: this.n, done: this.n == max };
+ this.n++;
+ return ret;
+ }
+ return { next: next, n: 0 }
+}
+
+function results(results) {
+ var i = 0;
+ function next() {
+ return results[i++];
+ }
+ return { next: next }
+}
+
+function* integers_from(n) {
+ while (1) yield n++;
+}
+
+// A destructive append.
+function append(x, tail) {
+ tail[tail.length] = x;
+ return tail;
+}
+
+function sum(x, tail) {
+ return x + tail;
+}
+
+function fold(cons, seed, iter) {
+ for (var x of iter) {
+ seed = cons(x, seed);
+ }
+ return seed;
+}
+
+function* take(iter, n) {
+ if (n == 0) return;
+ for (let x of iter) {
+ yield x;
+ if (--n == 0) break;
+ }
+}
+
+function nth(iter, n) {
+ for (let x of iter) {
+ if (n-- == 0) return x;
+ }
+ throw "unreachable";
+}
+
+function* skip_every(iter, n) {
+ var i = 0;
+ for (let x of iter) {
+ if (++i % n == 0) continue;
+ yield x;
+ }
+}
+
+function* iter_map(iter, f) {
+ for (var x of iter) {
+ yield f(x);
+ }
+}
+function nested_fold(cons, seed, iter) {
+ var visited = []
+ for (let x of iter) {
+ for (let y of x) {
+ seed = cons(y, seed);
+ }
+ }
+ return seed;
+}
+
+function* unreachable(iter) {
+ for (let x of iter) {
+ throw "not reached";
+ }
+}
+
+function one_time_getter(o, prop, val) {
+ function set_never() { throw "unreachable"; }
+ var gotten = false;
+ function get_once() {
+ if (gotten) throw "got twice";
+ gotten = true;
+ return val;
+ }
+ Object.defineProperty(o, prop, {get: get_once, set: set_never})
+ return o;
+}
+
+function never_getter(o, prop) {
+ function never() { throw "unreachable"; }
+ Object.defineProperty(o, prop, {get: never, set: never})
+ return o;
+}
+
+function remove_next_after(iter, n) {
+ function next() {
+ if (n-- == 0) delete this.next;
+ return iter.next();
+ }
+ return { next: next }
+}
+
+function poison_next_after(iter, n) {
+ function next() {
+ return iter.next();
+ }
+ function next_getter() {
+ if (n-- < 0)
+ throw "poisoned";
+ return next;
+ }
+ var o = {};
+ Object.defineProperty(o, 'next', { get: next_getter });
+ return o;
+}
+
+// Now, the tests.
+
+// Non-generator iterators.
+assertEquals(45, fold(sum, 0, integers_until(10)));
+// Generator iterators.
+assertEquals([1, 2, 3], fold(append, [], values(1, 2, 3)));
+// Break.
+assertEquals(45, fold(sum, 0, take(integers_from(0), 10)));
+// Continue.
+assertEquals(90, fold(sum, 0, take(skip_every(integers_from(0), 2), 10)));
+// Return.
+assertEquals(10, nth(integers_from(0), 10));
+// Nested for-of.
+assertEquals([0, 0, 1, 0, 1, 2, 0, 1, 2, 3],
+ nested_fold(append,
+ [],
+ iter_map(integers_until(5), integers_until)));
+// Result objects with sparse fields.
+assertEquals([undefined, 1, 2, 3],
+ fold(append, [],
+ results([{ done: false },
+ { value: 1, done: false },
+ // A missing "done" is the same as undefined, which
+ // is false.
+ { value: 2 },
+ // Not done.
+ { value: 3, done: 0 },
+ // Done.
+ { value: 4, done: 42 }])));
+// Results that are not objects.
+assertEquals([undefined, undefined, undefined],
+ fold(append, [],
+ results([10, "foo", /qux/, { value: 37, done: true }])));
+// Getters (shudder).
+assertEquals([1, 2],
+ fold(append, [],
+ results([one_time_getter({ value: 1 }, 'done', false),
+ one_time_getter({ done: false }, 'value', 2),
+ { value: 37, done: true },
+ never_getter(never_getter({}, 'done'), 'value')])));
+
+// Null and undefined do not cause an error.
+assertEquals(0, fold(sum, 0, unreachable(null)));
+assertEquals(0, fold(sum, 0, unreachable(undefined)));
+
+// Other non-iterators do cause an error.
+assertThrows('fold(sum, 0, unreachable({}))', TypeError);
+assertThrows('fold(sum, 0, unreachable("foo"))', TypeError);
+assertThrows('fold(sum, 0, unreachable(37))', TypeError);
+
+// "next" is looked up each time.
+assertThrows('fold(sum, 0, remove_next_after(integers_until(10), 5))',
+ TypeError);
+// It is not called at any other time.
+assertEquals(45,
+ fold(sum, 0, remove_next_after(integers_until(10), 10)));
+// It is not looked up too many times.
+assertEquals(45,
+ fold(sum, 0, poison_next_after(integers_until(10), 10)));
+
+function labelled_continue(iter) {
+ var n = 0;
+outer:
+ while (true) {
+ n++;
+ for (var x of iter) continue outer;
+ break;
+ }
+ return n;
+}
+assertEquals(11, labelled_continue(integers_until(10)));
+
+function labelled_break(iter) {
+ var n = 0;
+outer:
+ while (true) {
+ n++;
+ for (var x of iter) break outer;
+ }
+ return n;
+}
+assertEquals(1, labelled_break(integers_until(10)));
+
+// Test continue/break in catch.
+function catch_control(iter, k) {
+ var n = 0;
+ for (var x of iter) {
+ try {
+ return k(x);
+ } catch (e) {
+ if (e == "continue") continue;
+ else if (e == "break") break;
+ else throw e;
+ }
+ } while (false);
+ return false;
+}
+assertEquals(false,
+ catch_control(integers_until(10),
+ function() { throw "break" }));
+assertEquals(false,
+ catch_control(integers_until(10),
+ function() { throw "continue" }));
+assertEquals(5,
+ catch_control(integers_until(10),
+ function(x) {
+ if (x == 5) return x;
+ throw "continue";
+ }));
+
+// Test continue/break in try.
+function try_control(iter, k) {
+ var n = 0;
+ for (var x of iter) {
+ try {
+ var e = k(x);
+ if (e == "continue") continue;
+ else if (e == "break") break;
+ return e;
+ } catch (e) {
+ throw e;
+ }
+ } while (false);
+ return false;
+}
+assertEquals(false,
+ try_control(integers_until(10),
+ function() { return "break" }));
+assertEquals(false,
+ try_control(integers_until(10),
+ function() { return "continue" }));
+assertEquals(5,
+ try_control(integers_until(10),
+ function(x) { return (x == 5) ? x : "continue" }));
+
+// Proxy results, with getters.
+function transparent_proxy(x) {
+ return Proxy.create({
+ get: function(receiver, name) { return x[name]; }
+ });
+}
+assertEquals([1, 2],
+ fold(append, [],
+ results([one_time_getter({ value: 1 }, 'done', false),
+ one_time_getter({ done: false }, 'value', 2),
+ { value: 37, done: true },
+ never_getter(never_getter({}, 'done'), 'value')]
+ .map(transparent_proxy))));
+
+// Proxy iterators.
+function poison_proxy_after(x, n) {
+ return Proxy.create({
+ get: function(receiver, name) {
+ if (name == 'next' && n-- < 0) throw "unreachable";
+ return x[name];
+ },
+ // Needed for integers_until(10)'s this.n++.
+ set: function(receiver, name, val) {
+ return x[name] = val;
+ }
+ });
+}
+assertEquals(45, fold(sum, 0, poison_proxy_after(integers_until(10), 10)));
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698