1// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Flags: --expose-gc
29
30function Catch(f, g) {
31  var r;
32  try { r = f(); } catch (o) { return g(o); }
33  return r;
34}
35
36function CatchReturn(f, g) {
37  try { return f(); } catch (o) { return g(o); }
38}
39
40
41var a = [Catch, CatchReturn]
42for (var n in a) {
43  var c = a[n];
44  assertEquals(1, c(function() { return 1; }));
45  assertEquals('bar', c(function() { return 'bar'; }));
46  assertEquals(1, c(function () { throw 1; }, function (x) { return x; }));
47  assertEquals('bar', c(function () { throw 'bar'; }, function (x) { return x; }));
48}
49
50
51assertEquals(1, (function() { try { return 1; } finally { } })());
52assertEquals(1, (function() { try { return 1; } finally { var x = 12; } })());
53assertEquals(2, (function() { try { } finally { return 2; } })());
54assertEquals(4, (function() { try { return 3; } finally { return 4; } })());
55
56function f(x, n, v) { try { return x; } finally { x[n] = v; } }
57assertEquals(2, f({}, 'foo', 2).foo);
58assertEquals(5, f({}, 'bar', 5).bar);
59
60function guard(f) { try { f(); } catch (o) { return o; } }
61assertEquals('baz', guard(function() { throw 'baz'; }));
62assertEquals(2, (function() { try { throw {}; } catch(e) {} finally { return 2; } })());
63assertEquals(1, guard(function() { try { throw 1; } finally { } }));
64assertEquals(2, guard(function() { try { throw 2; } finally { var x = 12; } }));
65assertEquals(4, guard(function() { try { throw 3; } finally { throw 4; } }));
66
67(function () {
68  var iter = 1000000;
69  for (var i = 1; i <= iter; i++) {
70    try {
71      if (i == iter) gc();
72    } finally {
73      if (i == iter) gc();
74    }
75  }
76})();
77
78function trycatch(a) {
79  var o;
80  try {
81    throw 1;
82  } catch (o) {
83    a.push(o);
84    try {
85      throw 2;
86    } catch (o) {
87      a.push(o);
88    }
89    a.push(o);
90  }
91  a.push(o);
92}
93var a = [];
94trycatch(a);
95assertEquals(4, a.length);
96assertEquals(1, a[0], "a[0]");
97assertEquals(2, a[1], "a[1]");
98
99assertEquals(1, a[2], "a[2]");
100assertTrue(typeof a[3] === 'undefined', "a[3]");
101
102assertTrue(typeof o === 'undefined', "global.o");
103
104
105function return_from_nested_catch(x) {
106  try {
107    try {
108      return x;
109    } catch (o) {
110      return -1;
111    }
112  } catch (o) {
113    return -2;
114  }
115}
116
117assertEquals(0, return_from_nested_catch(0));
118assertEquals(1, return_from_nested_catch(1));
119
120
121function return_from_nested_finally(x) {
122  var a = [x-2];
123  try {
124    try {
125      return a;
126    } finally {
127      a[0]++;
128    }
129  } finally {
130    a[0]++;
131  }
132}
133
134assertEquals(0, return_from_nested_finally(0)[0]);
135assertEquals(1, return_from_nested_finally(1)[0]);
136
137
138function break_from_catch(x) {
139  x--;
140 L:
141  {
142    try {
143      x++;
144      if (false) return -1;
145      break L;
146    } catch (o) {
147      x--;
148    }
149  }
150  return x;
151}
152
153assertEquals(0, break_from_catch(0));
154assertEquals(1, break_from_catch(1));
155
156
157function break_from_finally(x) {
158 L:
159  {
160    try {
161      x++;
162      if (false) return -1;
163      break L;
164    } finally {
165      x--;
166    }
167    x--;
168  }
169  return x;
170}
171
172assertEquals(0, break_from_finally(0), "break from finally");
173assertEquals(1, break_from_finally(1), "break from finally");
174
175
176function continue_from_catch(x) {
177  x--;
178  var cont = true;
179  while (cont) {
180    try {
181      x++;
182      if (false) return -1;
183      cont = false;
184      continue;
185    } catch (o) {
186      x--;
187    }
188  }
189  return x;
190}
191
192assertEquals(0, continue_from_catch(0));
193assertEquals(1, continue_from_catch(1));
194
195
196function continue_from_finally(x) {
197  var cont = true;
198  while (cont) {
199    try {
200      x++;
201      if (false) return -1;
202      cont = false;
203      continue;
204    } finally {
205      x--;
206    }
207    x--;
208  }
209  return x;
210}
211
212assertEquals(0, continue_from_finally(0));
213assertEquals(1, continue_from_finally(1));
214
215
216function continue_alot_from_finally(x) {
217  var j = 0;
218  for (var i = 0; i < x;) {
219    try {
220      j++;
221      continue;
222      j++;  // should not happen
223    } finally {
224      i++; // must happen
225    }
226    j++; // should not happen
227  }
228  return j;
229}
230
231
232assertEquals(100, continue_alot_from_finally(100));
233assertEquals(200, continue_alot_from_finally(200));
234
235
236
237function break_from_nested_catch(x) {
238  x -= 2;
239 L:
240  {
241    try {
242      x++;
243      try {
244        x++;
245        if (false) return -1;
246        break L;
247      } catch (o) {
248        x--;
249      }
250    } catch (o) {
251      x--;
252    }
253  }
254  return x;
255}
256
257assertEquals(0, break_from_nested_catch(0));
258assertEquals(1, break_from_nested_catch(1));
259
260
261function break_from_nested_finally(x) {
262 L:
263  {
264    try {
265      x++;
266      try {
267        x++;
268        if (false) return -1;
269        break L;
270      } finally {
271        x--;
272      }
273    } finally {
274      x--;
275    }
276    x--; // should not happen
277  }
278  return x;
279}
280
281assertEquals(0, break_from_nested_finally(0));
282assertEquals(1, break_from_nested_finally(1));
283
284
285function continue_from_nested_catch(x) {
286  x -= 2;
287  var cont = true;
288  while (cont) {
289    try {
290      x++;
291      try {
292        x++;
293        if (false) return -1;
294        cont = false;
295        continue;
296      } catch (o) {
297        x--;
298      }
299    } catch (o) {
300      x--;
301    }
302  }
303  return x;
304}
305
306assertEquals(0, continue_from_nested_catch(0));
307assertEquals(1, continue_from_nested_catch(1));
308
309
310function continue_from_nested_finally(x) {
311  var cont = true;
312  while (cont) {
313    try {
314      x++;
315      try {
316        x++;
317        if (false) return -1;
318        cont = false;
319        continue;
320      } finally {
321        x--;
322      }
323    } finally {
324      x--;
325    }
326    x--;  // should not happen
327  }
328  return x;
329}
330
331assertEquals(0, continue_from_nested_finally(0));
332assertEquals(1, continue_from_nested_finally(1));
333
334
335var caught = false;
336var finalized = false;
337var broke = true;
338L: try {
339  break L;
340  broke = false;
341} catch (o) {
342  caught = true;
343} finally {
344  finalized = true;
345}
346assertTrue(broke);
347assertFalse(caught);
348assertTrue(finalized);
349
350function return_from_nested_finally_in_finally() {
351  try {
352    return 1;
353  } finally {
354    try {
355      return 2;
356    } finally {
357      return 42;
358    }
359  }
360}
361
362assertEquals(42, return_from_nested_finally_in_finally());
363
364function break_from_nested_finally_in_finally() {
365  L: try {
366    return 1;
367  } finally {
368    try {
369      return 2;
370    } finally {
371      break L;
372    }
373  }
374  return 42;
375}
376
377assertEquals(42, break_from_nested_finally_in_finally());
378
379function continue_from_nested_finally_in_finally() {
380  do {
381    try {
382      return 1;
383    } finally {
384      try {
385        return 2;
386      } finally {
387        continue;
388      }
389    }
390  } while (false);
391  return 42;
392}
393
394assertEquals(42, continue_from_nested_finally_in_finally());
395