// Copyright 2008 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: --expose-gc
function Catch(f, g) {
var r;
try { r = f(); } catch (o) { return g(o); }
return r;
}
function CatchReturn(f, g) {
try { return f(); } catch (o) { return g(o); }
}
var a = [Catch, CatchReturn]
for (var n in a) {
var c = a[n];
assertEquals(1, c(function() { return 1; }));
assertEquals('bar', c(function() { return 'bar'; }));
assertEquals(1, c(function () { throw 1; }, function (x) { return x; }));
assertEquals('bar', c(function () { throw 'bar'; }, function (x) { return x; }));
}
assertEquals(1, (function() { try { return 1; } finally { } })());
assertEquals(1, (function() { try { return 1; } finally { var x = 12; } })());
assertEquals(2, (function() { try { } finally { return 2; } })());
assertEquals(4, (function() { try { return 3; } finally { return 4; } })());
function f(x, n, v) { try { return x; } finally { x[n] = v; } }
assertEquals(2, f({}, 'foo', 2).foo);
assertEquals(5, f({}, 'bar', 5).bar);
function guard(f) { try { f(); } catch (o) { return o; } }
assertEquals('baz', guard(function() { throw 'baz'; }));
assertEquals(2, (function() { try { throw {}; } catch(e) {} finally { return 2; } })());
assertEquals(1, guard(function() { try { throw 1; } finally { } }));
assertEquals(2, guard(function() { try { throw 2; } finally { var x = 12; } }));
assertEquals(4, guard(function() { try { throw 3; } finally { throw 4; } }));
(function () {
var iter = 1000000;
for (var i = 1; i <= iter; i++) {
try {
if (i == iter) gc();
} finally {
if (i == iter) gc();
}
}
})();
function trycatch(a) {
var o;
try {
throw 1;
} catch (o) {
a.push(o);
try {
throw 2;
} catch (o) {
a.push(o);
}
a.push(o);
}
a.push(o);
}
var a = [];
trycatch(a);
assertEquals(4, a.length);
assertEquals(1, a[0], "a[0]");
assertEquals(2, a[1], "a[1]");
assertEquals(1, a[2], "a[2]");
assertTrue(typeof a[3] === 'undefined', "a[3]");
assertTrue(typeof o === 'undefined', "global.o");
function return_from_nested_catch(x) {
try {
try {
return x;
} catch (o) {
return -1;
}
} catch (o) {
return -2;
}
}
assertEquals(0, return_from_nested_catch(0));
assertEquals(1, return_from_nested_catch(1));
function return_from_nested_finally(x) {
var a = [x-2];
try {
try {
return a;
} finally {
a[0]++;
}
} finally {
a[0]++;
}
}
assertEquals(0, return_from_nested_finally(0)[0]);
assertEquals(1, return_from_nested_finally(1)[0]);
function break_from_catch(x) {
x--;
L:
{
try {
x++;
if (false) return -1;
break L;
} catch (o) {
x--;
}
}
return x;
}
assertEquals(0, break_from_catch(0));
assertEquals(1, break_from_catch(1));
function break_from_finally(x) {
L:
{
try {
x++;
if (false) return -1;
break L;
} finally {
x--;
}
x--;
}
return x;
}
assertEquals(0, break_from_finally(0), "break from finally");
assertEquals(1, break_from_finally(1), "break from finally");
function continue_from_catch(x) {
x--;
var cont = true;
while (cont) {
try {
x++;
if (false) return -1;
cont = false;
continue;
} catch (o) {
x--;
}
}
return x;
}
assertEquals(0, continue_from_catch(0));
assertEquals(1, continue_from_catch(1));
function continue_from_finally(x) {
var cont = true;
while (cont) {
try {
x++;
if (false) return -1;
cont = false;
continue;
} finally {
x--;
}
x--;
}
return x;
}
assertEquals(0, continue_from_finally(0));
assertEquals(1, continue_from_finally(1));
function continue_alot_from_finally(x) {
var j = 0;
for (var i = 0; i < x;) {
try {
j++;
continue;
j++; // should not happen
} finally {
i++; // must happen
}
j++; // should not happen
}
return j;
}
assertEquals(100, continue_alot_from_finally(100));
assertEquals(200, continue_alot_from_finally(200));
function break_from_nested_catch(x) {
x -= 2;
L:
{
try {
x++;
try {
x++;
if (false) return -1;
break L;
} catch (o) {
x--;
}
} catch (o) {
x--;
}
}
return x;
}
assertEquals(0, break_from_nested_catch(0));
assertEquals(1, break_from_nested_catch(1));
function break_from_nested_finally(x) {
L:
{
try {
x++;
try {
x++;
if (false) return -1;
break L;
} finally {
x--;
}
} finally {
x--;
}
x--; // should not happen
}
return x;
}
assertEquals(0, break_from_nested_finally(0));
assertEquals(1, break_from_nested_finally(1));
function continue_from_nested_catch(x) {
x -= 2;
var cont = true;
while (cont) {
try {
x++;
try {
x++;
if (false) return -1;
cont = false;
continue;
} catch (o) {
x--;
}
} catch (o) {
x--;
}
}
return x;
}
assertEquals(0, continue_from_nested_catch(0));
assertEquals(1, continue_from_nested_catch(1));
function continue_from_nested_finally(x) {
var cont = true;
while (cont) {
try {
x++;
try {
x++;
if (false) return -1;
cont = false;
continue;
} finally {
x--;
}
} finally {
x--;
}
x--; // should not happen
}
return x;
}
assertEquals(0, continue_from_nested_finally(0));
assertEquals(1, continue_from_nested_finally(1));
var caught = false;
var finalized = false;
var broke = true;
L: try {
break L;
broke = false;
} catch (o) {
caught = true;
} finally {
finalized = true;
}
assertTrue(broke);
assertFalse(caught);
assertTrue(finalized);
function return_from_nested_finally_in_finally() {
try {
return 1;
} finally {
try {
return 2;
} finally {
return 42;
}
}
}
assertEquals(42, return_from_nested_finally_in_finally());
function break_from_nested_finally_in_finally() {
L: try {
return 1;
} finally {
try {
return 2;
} finally {
break L;
}
}
return 42;
}
assertEquals(42, break_from_nested_finally_in_finally());
function continue_from_nested_finally_in_finally() {
do {
try {
return 1;
} finally {
try {
return 2;
} finally {
continue;
}
}
} while (false);
return 42;
}
assertEquals(42, continue_from_nested_finally_in_finally());