// return value in try block should not be overridden by yield in finally block.

load(libdir + "asserts.js");

// simple
function* g1() {
  try {
    return 42;
  } finally {
    yield 43;
  }
}
var o = g1();
var v = o.next();
assertEq(v.done, false);
assertEq(v.value, 43);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, 42);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);

// without return value
function* g2() {
  try {
    return;
  } finally {
    yield 43;
  }
}
o = g2();
v = o.next();
assertEq(v.done, false);
assertEq(v.value, 43);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);

// nested try-finally
function* g3() {
  try {
    try {
      return 42;
    } finally {
      try {
        return 43;
      } finally {
        yield 44;
      }
    }
  } finally {
    yield 45;
  }
}
o = g3();
v = o.next();
assertEq(v.done, false);
assertEq(v.value, 44);
v = o.next();
assertEq(v.done, false);
assertEq(v.value, 45);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, 43);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);

// yield*
function* g4() {
  try {
    return 42;
  } finally {
    try {
      return 43;
    } finally {
      yield* g5();
    }
  }
}
function* g5() {
  yield 44;
  return 45;
}
o = g4();
v = o.next();
assertEq(v.done, false);
assertEq(v.value, 44);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, 43);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);

// return in block scope
function* g6() {
  let a = 10;
  {
    let a = 20;
    try {
      let a = 30;
      {
        let a = 40;
        return 42;
      }
    } finally {
      yield 43;
    }
  }
}
o = g6();
v = o.next();
assertEq(v.done, false);
assertEq(v.value, 43);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, 42);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);

// no finally
function* g7() {
  try {
    return 42;
  } catch (e) {
    yield 1;
  }
}
o = g7();
v = o.next();
assertEq(v.done, true);
assertEq(v.value, 42);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);

// in "with" statement
eval(`
function* g9() {
  with ({ ".genrval": { value: 44, done: false } }) {
    try {
      return 42;
    } finally {
      yield 43;
    }
  }
}
o = g9();
v = o.next();
assertEq(v.done, false);
assertEq(v.value, 43);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, 42);
v = o.next();
assertEq(v.done, true);
assertEq(v.value, undefined);
`);