Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "test/cctest/compiler/function-tester.h"
      6 
      7 namespace v8 {
      8 namespace internal {
      9 namespace compiler {
     10 
     11 TEST(Throw) {
     12   FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})");
     13 
     14   T.CheckThrows(T.true_value(), T.NewObject("new Error"));
     15   T.CheckCall(T.Val(23), T.false_value(), T.Val(23));
     16 }
     17 
     18 
     19 TEST(ThrowMessagePosition) {
     20   static const char* src =
     21       "(function(a, b) {        \n"
     22       "  if (a == 1) throw 1;   \n"
     23       "  if (a == 2) {throw 2}  \n"
     24       "  if (a == 3) {0;throw 3}\n"
     25       "  throw 4;               \n"
     26       "})                       ";
     27   FunctionTester T(src);
     28   v8::Local<v8::Message> message;
     29   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
     30 
     31   message = T.CheckThrowsReturnMessage(T.Val(1), T.undefined());
     32   CHECK_EQ(2, message->GetLineNumber(context).FromMaybe(-1));
     33   CHECK_EQ(40, message->GetStartPosition());
     34 
     35   message = T.CheckThrowsReturnMessage(T.Val(2), T.undefined());
     36   CHECK_EQ(3, message->GetLineNumber(context).FromMaybe(-1));
     37   CHECK_EQ(67, message->GetStartPosition());
     38 
     39   message = T.CheckThrowsReturnMessage(T.Val(3), T.undefined());
     40   CHECK_EQ(4, message->GetLineNumber(context).FromMaybe(-1));
     41   CHECK_EQ(95, message->GetStartPosition());
     42 }
     43 
     44 
     45 TEST(ThrowMessageDirectly) {
     46   static const char* src =
     47       "(function(a, b) {"
     48       "  if (a) { throw b; } else { throw new Error(b); }"
     49       "})";
     50   FunctionTester T(src);
     51   v8::Local<v8::Message> message;
     52   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
     53   v8::Maybe<bool> t = v8::Just(true);
     54 
     55   message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
     56   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?")));
     57 
     58   message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
     59   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!")));
     60 }
     61 
     62 
     63 TEST(ThrowMessageIndirectly) {
     64   static const char* src =
     65       "(function(a, b) {"
     66       "  try {"
     67       "    if (a) { throw b; } else { throw new Error(b); }"
     68       "  } finally {"
     69       "    try { throw 'clobber'; } catch (e) { 'unclobber'; }"
     70       "  }"
     71       "})";
     72   FunctionTester T(src);
     73   v8::Local<v8::Message> message;
     74   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
     75   v8::Maybe<bool> t = v8::Just(true);
     76 
     77   message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
     78   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?")));
     79 
     80   message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
     81   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!")));
     82 }
     83 
     84 
     85 TEST(Catch) {
     86   const char* src =
     87       "(function(a,b) {"
     88       "  var r = '-';"
     89       "  try {"
     90       "    r += 'A-';"
     91       "    throw 'B-';"
     92       "  } catch (e) {"
     93       "    r += e;"
     94       "  }"
     95       "  return r;"
     96       "})";
     97   FunctionTester T(src);
     98 
     99   T.CheckCall(T.Val("-A-B-"));
    100 }
    101 
    102 
    103 TEST(CatchNested) {
    104   const char* src =
    105       "(function(a,b) {"
    106       "  var r = '-';"
    107       "  try {"
    108       "    r += 'A-';"
    109       "    throw 'C-';"
    110       "  } catch (e) {"
    111       "    try {"
    112       "      throw 'B-';"
    113       "    } catch (e) {"
    114       "      r += e;"
    115       "    }"
    116       "    r += e;"
    117       "  }"
    118       "  return r;"
    119       "})";
    120   FunctionTester T(src);
    121 
    122   T.CheckCall(T.Val("-A-B-C-"));
    123 }
    124 
    125 
    126 TEST(CatchBreak) {
    127   const char* src =
    128       "(function(a,b) {"
    129       "  var r = '-';"
    130       "  L: try {"
    131       "    r += 'A-';"
    132       "    if (a) break L;"
    133       "    r += 'B-';"
    134       "    throw 'C-';"
    135       "  } catch (e) {"
    136       "    if (b) break L;"
    137       "    r += e;"
    138       "  }"
    139       "  r += 'D-';"
    140       "  return r;"
    141       "})";
    142   FunctionTester T(src);
    143 
    144   T.CheckCall(T.Val("-A-D-"), T.true_value(), T.false_value());
    145   T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
    146   T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
    147 }
    148 
    149 
    150 TEST(CatchCall) {
    151   const char* src =
    152       "(function(fun) {"
    153       "  var r = '-';"
    154       "  try {"
    155       "    r += 'A-';"
    156       "    return r + 'B-' + fun();"
    157       "  } catch (e) {"
    158       "    r += e;"
    159       "  }"
    160       "  return r;"
    161       "})";
    162   FunctionTester T(src);
    163 
    164   CompileRun("function thrower() { throw 'T-'; }");
    165   T.CheckCall(T.Val("-A-T-"), T.NewFunction("thrower"));
    166   CompileRun("function returner() { return 'R-'; }");
    167   T.CheckCall(T.Val("-A-B-R-"), T.NewFunction("returner"));
    168 }
    169 
    170 
    171 TEST(Finally) {
    172   const char* src =
    173       "(function(a,b) {"
    174       "  var r = '-';"
    175       "  try {"
    176       "    r += 'A-';"
    177       "  } finally {"
    178       "    r += 'B-';"
    179       "  }"
    180       "  return r;"
    181       "})";
    182   FunctionTester T(src);
    183 
    184   T.CheckCall(T.Val("-A-B-"));
    185 }
    186 
    187 
    188 TEST(FinallyBreak) {
    189   const char* src =
    190       "(function(a,b) {"
    191       "  var r = '-';"
    192       "  L: try {"
    193       "    r += 'A-';"
    194       "    if (a) return r;"
    195       "    r += 'B-';"
    196       "    if (b) break L;"
    197       "    r += 'C-';"
    198       "  } finally {"
    199       "    r += 'D-';"
    200       "  }"
    201       "  return r;"
    202       "})";
    203   FunctionTester T(src);
    204 
    205   T.CheckCall(T.Val("-A-"), T.true_value(), T.false_value());
    206   T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
    207   T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
    208 }
    209 
    210 
    211 TEST(DeoptTry) {
    212   const char* src =
    213       "(function f(a) {"
    214       "  try {"
    215       "    %DeoptimizeFunction(f);"
    216       "    throw a;"
    217       "  } catch (e) {"
    218       "    return e + 1;"
    219       "  }"
    220       "})";
    221   FunctionTester T(src);
    222 
    223   T.CheckCall(T.Val(2), T.Val(1));
    224 }
    225 
    226 
    227 TEST(DeoptCatch) {
    228   const char* src =
    229       "(function f(a) {"
    230       "  try {"
    231       "    throw a;"
    232       "  } catch (e) {"
    233       "    %DeoptimizeFunction(f);"
    234       "    return e + 1;"
    235       "  }"
    236       "})";
    237   FunctionTester T(src);
    238 
    239   T.CheckCall(T.Val(2), T.Val(1));
    240 }
    241 
    242 
    243 TEST(DeoptFinallyReturn) {
    244   const char* src =
    245       "(function f(a) {"
    246       "  try {"
    247       "    throw a;"
    248       "  } finally {"
    249       "    %DeoptimizeFunction(f);"
    250       "    return a + 1;"
    251       "  }"
    252       "})";
    253   FunctionTester T(src);
    254 
    255   T.CheckCall(T.Val(2), T.Val(1));
    256 }
    257 
    258 
    259 TEST(DeoptFinallyReThrow) {
    260   const char* src =
    261       "(function f(a) {"
    262       "  try {"
    263       "    throw a;"
    264       "  } finally {"
    265       "    %DeoptimizeFunction(f);"
    266       "  }"
    267       "})";
    268   FunctionTester T(src);
    269 
    270   T.CheckThrows(T.NewObject("new Error"), T.Val(1));
    271 }
    272 
    273 }  // namespace compiler
    274 }  // namespace internal
    275 }  // namespace v8
    276