Upgrade to 3.29

Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.

Bug: 17370214

Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/test/mjsunit/es6/iteration-semantics.js b/test/mjsunit/es6/iteration-semantics.js
new file mode 100644
index 0000000..544c94d
--- /dev/null
+++ b/test/mjsunit/es6/iteration-semantics.js
@@ -0,0 +1,336 @@
+// 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-scoping --harmony-proxies
+
+// Test for-of semantics.
+
+"use strict";
+
+
+// First, some helpers.
+
+function* values() {
+  for (var i = 0; i < arguments.length; i++) {
+    yield arguments[i];
+  }
+}
+
+function wrap_iterator(iterator) {
+    var iterable = {};
+    iterable[Symbol.iterator] = function() { return iterator; };
+    return iterable;
+}
+
+function integers_until(max) {
+  function next() {
+    var ret = { value: this.n, done: this.n == max };
+    this.n++;
+    return ret;
+  }
+  return wrap_iterator({ next: next, n: 0 });
+}
+
+function results(results) {
+  var i = 0;
+  function next() {
+    return results[i++];
+  }
+  return wrap_iterator({ 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, iterable) {
+  for (var x of iterable) {
+    seed = cons(x, seed);
+  }
+  return seed;
+}
+
+function* take(iterable, n) {
+  if (n == 0) return;
+  for (let x of iterable) {
+    yield x;
+    if (--n == 0) break;
+  }
+}
+
+function nth(iterable, n) {
+  for (let x of iterable) {
+    if (n-- == 0) return x;
+  }
+  throw "unreachable";
+}
+
+function* skip_every(iterable, n) {
+  var i = 0;
+  for (let x of iterable) {
+    if (++i % n == 0) continue;
+    yield x;
+  }
+}
+
+function* iter_map(iterable, f) {
+  for (var x of iterable) {
+    yield f(x);
+  }
+}
+function nested_fold(cons, seed, iterable) {
+  var visited = []
+  for (let x of iterable) {
+    for (let y of x) {
+      seed = cons(y, seed);
+    }
+  }
+  return seed;
+}
+
+function* unreachable(iterable) {
+  for (let x of iterable) {
+    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(iterable, n) {
+  var iterator = iterable[Symbol.iterator]();
+  function next() {
+    if (n-- == 0) delete this.next;
+    return iterator.next();
+  }
+  return wrap_iterator({ next: next });
+}
+
+function poison_next_after(iterable, n) {
+  var iterator = iterable[Symbol.iterator]();
+  function next() {
+    return iterator.next();
+  }
+  function next_getter() {
+    if (n-- < 0)
+      throw "poisoned";
+    return next;
+  }
+  var o = {};
+  Object.defineProperty(o, 'next', { get: next_getter });
+  return wrap_iterator(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')])));
+
+// Unlike the case with for-in, null and undefined cause an error.
+assertThrows('fold(sum, 0, unreachable(null))', TypeError);
+assertThrows('fold(sum, 0, unreachable(undefined))', TypeError);
+
+// Other non-iterators do cause an error.
+assertThrows('fold(sum, 0, unreachable({}))', TypeError);
+assertThrows('fold(sum, 0, unreachable(false))', 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(iterable) {
+  var n = 0;
+outer:
+  while (true) {
+    n++;
+    for (var x of iterable) continue outer;
+    break;
+  }
+  return n;
+}
+assertEquals(11, labelled_continue(integers_until(10)));
+
+function labelled_break(iterable) {
+  var n = 0;
+outer:
+  while (true) {
+    n++;
+    for (var x of iterable) break outer;
+  }
+  return n;
+}
+assertEquals(1, labelled_break(integers_until(10)));
+
+// Test continue/break in catch.
+function catch_control(iterable, k) {
+  var n = 0;
+  for (var x of iterable) {
+    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(iterable, k) {
+  var n = 0;
+  for (var x of iterable) {
+    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(iterable, n) {
+  var iterator = iterable[Symbol.iterator]();
+  return wrap_iterator(Proxy.create({
+    get: function(receiver, name) {
+      if (name == 'next' && n-- < 0) throw "unreachable";
+      return iterator[name];
+    },
+    // Needed for integers_until(10)'s this.n++.
+    set: function(receiver, name, val) {
+      return iterator[name] = val;
+    }
+  }));
+}
+assertEquals(45, fold(sum, 0, poison_proxy_after(integers_until(10), 10)));