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   i::FLAG_turbo_try_finally = true;
     65   static const char* src =
     66       "(function(a, b) {"
     67       "  try {"
     68       "    if (a) { throw b; } else { throw new Error(b); }"
     69       "  } finally {"
     70       "    try { throw 'clobber'; } catch (e) { 'unclobber'; }"
     71       "  }"
     72       "})";
     73   FunctionTester T(src);
     74   v8::Local<v8::Message> message;
     75   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
     76   v8::Maybe<bool> t = v8::Just(true);
     77 
     78   message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
     79   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?")));
     80 
     81   message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
     82   CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!")));
     83 }
     84 
     85 
     86 TEST(Catch) {
     87   const char* src =
     88       "(function(a,b) {"
     89       "  var r = '-';"
     90       "  try {"
     91       "    r += 'A-';"
     92       "    throw 'B-';"
     93       "  } catch (e) {"
     94       "    r += e;"
     95       "  }"
     96       "  return r;"
     97       "})";
     98   FunctionTester T(src);
     99 
    100   T.CheckCall(T.Val("-A-B-"));
    101 }
    102 
    103 
    104 TEST(CatchNested) {
    105   const char* src =
    106       "(function(a,b) {"
    107       "  var r = '-';"
    108       "  try {"
    109       "    r += 'A-';"
    110       "    throw 'C-';"
    111       "  } catch (e) {"
    112       "    try {"
    113       "      throw 'B-';"
    114       "    } catch (e) {"
    115       "      r += e;"
    116       "    }"
    117       "    r += e;"
    118       "  }"
    119       "  return r;"
    120       "})";
    121   FunctionTester T(src);
    122 
    123   T.CheckCall(T.Val("-A-B-C-"));
    124 }
    125 
    126 
    127 TEST(CatchBreak) {
    128   const char* src =
    129       "(function(a,b) {"
    130       "  var r = '-';"
    131       "  L: try {"
    132       "    r += 'A-';"
    133       "    if (a) break L;"
    134       "    r += 'B-';"
    135       "    throw 'C-';"
    136       "  } catch (e) {"
    137       "    if (b) break L;"
    138       "    r += e;"
    139       "  }"
    140       "  r += 'D-';"
    141       "  return r;"
    142       "})";
    143   FunctionTester T(src);
    144 
    145   T.CheckCall(T.Val("-A-D-"), T.true_value(), T.false_value());
    146   T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
    147   T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
    148 }
    149 
    150 
    151 TEST(CatchCall) {
    152   const char* src =
    153       "(function(fun) {"
    154       "  var r = '-';"
    155       "  try {"
    156       "    r += 'A-';"
    157       "    return r + 'B-' + fun();"
    158       "  } catch (e) {"
    159       "    r += e;"
    160       "  }"
    161       "  return r;"
    162       "})";
    163   FunctionTester T(src);
    164 
    165   CompileRun("function thrower() { throw 'T-'; }");
    166   T.CheckCall(T.Val("-A-T-"), T.NewFunction("thrower"));
    167   CompileRun("function returner() { return 'R-'; }");
    168   T.CheckCall(T.Val("-A-B-R-"), T.NewFunction("returner"));
    169 }
    170 
    171 
    172 TEST(Finally) {
    173   i::FLAG_turbo_try_finally = true;
    174   const char* src =
    175       "(function(a,b) {"
    176       "  var r = '-';"
    177       "  try {"
    178       "    r += 'A-';"
    179       "  } finally {"
    180       "    r += 'B-';"
    181       "  }"
    182       "  return r;"
    183       "})";
    184   FunctionTester T(src);
    185 
    186   T.CheckCall(T.Val("-A-B-"));
    187 }
    188 
    189 
    190 TEST(FinallyBreak) {
    191   i::FLAG_turbo_try_finally = true;
    192   const char* src =
    193       "(function(a,b) {"
    194       "  var r = '-';"
    195       "  L: try {"
    196       "    r += 'A-';"
    197       "    if (a) return r;"
    198       "    r += 'B-';"
    199       "    if (b) break L;"
    200       "    r += 'C-';"
    201       "  } finally {"
    202       "    r += 'D-';"
    203       "  }"
    204       "  return r;"
    205       "})";
    206   FunctionTester T(src);
    207 
    208   T.CheckCall(T.Val("-A-"), T.true_value(), T.false_value());
    209   T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
    210   T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
    211 }
    212 
    213 
    214 TEST(DeoptTry) {
    215   const char* src =
    216       "(function f(a) {"
    217       "  try {"
    218       "    %DeoptimizeFunction(f);"
    219       "    throw a;"
    220       "  } catch (e) {"
    221       "    return e + 1;"
    222       "  }"
    223       "})";
    224   FunctionTester T(src);
    225 
    226   T.CheckCall(T.Val(2), T.Val(1));
    227 }
    228 
    229 
    230 TEST(DeoptCatch) {
    231   const char* src =
    232       "(function f(a) {"
    233       "  try {"
    234       "    throw a;"
    235       "  } catch (e) {"
    236       "    %DeoptimizeFunction(f);"
    237       "    return e + 1;"
    238       "  }"
    239       "})";
    240   FunctionTester T(src);
    241 
    242   T.CheckCall(T.Val(2), T.Val(1));
    243 }
    244 
    245 
    246 TEST(DeoptFinallyReturn) {
    247   i::FLAG_turbo_try_finally = true;
    248   const char* src =
    249       "(function f(a) {"
    250       "  try {"
    251       "    throw a;"
    252       "  } finally {"
    253       "    %DeoptimizeFunction(f);"
    254       "    return a + 1;"
    255       "  }"
    256       "})";
    257   FunctionTester T(src);
    258 
    259   T.CheckCall(T.Val(2), T.Val(1));
    260 }
    261 
    262 
    263 TEST(DeoptFinallyReThrow) {
    264   i::FLAG_turbo_try_finally = true;
    265   const char* src =
    266       "(function f(a) {"
    267       "  try {"
    268       "    throw a;"
    269       "  } finally {"
    270       "    %DeoptimizeFunction(f);"
    271       "  }"
    272       "})";
    273   FunctionTester T(src);
    274 
    275 #if 0  // TODO(mstarzinger): Enable once we can.
    276   T.CheckThrows(T.NewObject("new Error"), T.Val(1));
    277 #endif
    278 }
    279 
    280 }  // namespace compiler
    281 }  // namespace internal
    282 }  // namespace v8
    283