Merge V8 5.2.361.47  DO NOT MERGE

https://chromium.googlesource.com/v8/v8/+/5.2.361.47

FPIIM-449

Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/test/mjsunit/harmony/iterator-close.js b/test/mjsunit/harmony/iterator-close.js
index 09e0153..03cdeac 100644
--- a/test/mjsunit/harmony/iterator-close.js
+++ b/test/mjsunit/harmony/iterator-close.js
@@ -1007,6 +1007,26 @@
   assertThrowsEquals(() => {
     (([x]) => x)(g());
   }, 666);
+
+  assertThrowsEquals(() => {
+    var [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([...x]) => x)(g());
+  }, 666);
 }
 
 
@@ -1051,6 +1071,26 @@
   assertThrowsEquals(() => {
     (([x]) => x)(g());
   }, 666);
+
+  assertThrowsEquals(() => {
+    var [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([...x]) => x)(g());
+  }, 666);
 }
 
 
@@ -1095,6 +1135,26 @@
   assertThrowsEquals(() => {
     (([x]) => x)(g());
   }, 666);
+
+  assertThrowsEquals(() => {
+    var [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([...x]) => x)(g());
+  }, 666);
 }
 
 
@@ -1238,3 +1298,75 @@
   }, 5);
   assertEquals([1], log);
 }
+
+
+// yield*, argument's return method is "undefined".
+function TestYieldStarWithoutReturn(get_iterable) {
+  assertTrue(get_iterable().return == undefined);
+
+  function* g() { yield* get_iterable() }
+
+  {
+    let gen = g();
+    assertEquals({value: 1, done: false}, gen.next());
+    assertEquals({value: undefined, done: true}, gen.return());
+  }
+
+  assertEquals(42, (() => {
+    for (let x of g()) break;
+    return 42;
+  })());
+
+  assertEquals(42, (() => {
+    for (let x of g()) return 42;
+  })());
+
+  assertThrowsEquals(() => {
+    for (let x of g()) throw 42;
+  }, 42);
+}
+{
+  let get_iterable1 = () => [1, 2];
+  let get_iterable2 = function*() { yield 1; yield 2 };
+  get_iterable2.prototype.return = null;
+  TestYieldStarWithoutReturn(get_iterable1);
+  TestYieldStarWithoutReturn(get_iterable2);
+}
+
+
+// yield*, argument's return method is defined.
+{
+  let get_iterable = function*() { yield 1; yield 2 };
+  const obj = {};
+  get_iterable.prototype.return = (...args) => obj;
+
+  function* g() { yield* get_iterable() }
+
+  {
+    let gen = g();
+    assertEquals({value: 1, done: false}, gen.next());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertEquals({value: 2, done: false}, gen.next());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertEquals({value: undefined, done: true}, gen.next());
+    assertEquals({value: undefined, done: true}, gen.return());
+    assertEquals({value: undefined, done: true}, gen.return());
+  }
+
+  assertEquals(42, (() => {
+    for (let x of g()) break;
+    return 42;
+  })());
+
+  assertEquals(42, (() => {
+    for (let x of g()) return 42;
+  })());
+
+  assertThrowsEquals(() => {
+    for (let x of g()) throw 42;
+  }, 42);
+}